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 l'é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 l'entrée de l'utilisateur directement sur son appareil. L'utilisateur reçoit un feedback immédiat et peut corriger les erreurs dans son entrée 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, ce qui 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 qu'il contient le
@symbole, appelez la classeValidationdu service de carte du module complémentaire Google Workspace. - Pour une validation robuste, comme comparer les valeurs de widget avec d'autres valeurs de widget
vous pouvez ajouter une validation CEL (Common Expression Language)
aux widgets de carte 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 CEL (Common Expression Language) offre des vérifications instantanées des entrées sans la latence de la validation côté serveur en déchargeant les vérifications de valeurs d'entrée qui ne dépendent pas de la recherche de données provenant d'autres services 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 entrées.
La création d'une validation CEL complète implique les composants suivants :
ExpressionDatadans la carte : contient la logique de validation spécifiée et la logique de déclenchement du widget lorsque l'une des conditions définies est remplie.Id: identifiant unique de l'élémentExpressionDatadans 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 à l'élémentEventActioncôté widget viaTriggersavec unactionRuleIdpartagé.EventActionau niveau de la carte : active les validations CEL dans la carte et associe le champExpressionDataaux widgets de résultat via des déclencheurs post-événement.actionRuleId: ID unique de cet élémentEventAction.ExpressionDataAction: défini surSTART_EXPRESSION_EVALUATIONpour indiquer que cette action démarre l'évaluation CEL.Trigger: connecte lesConditionsaux élémentsEventActionscôté widget en fonction de l'élémentactionRuleId.
EventActionau niveau du widget : contrôle le comportement du widget de résultat lorsque la condition de réussite ou d'échec est remplie. Un widget de résultat, par exemple, peut être un élémentTextParagraphqui contient un message d'erreur qui n'est visible que lorsque la validation échoue.actionRuleId: correspond à l'élémentactionRuleIddans leTriggercôté carte.CommonWidgetAction: définit les actions qui n'impliquent pas d'évaluations, comme la mise à jour de la visibilité du widget.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.
-
Figure 1 : lorsque la failConditionest remplie (les entrées ne sont pas égales), le widget de message d'erreur est défini surVISIBLEet s’affiche. -
Figure 2 : Lorsque la successConditionest remplie (les entrées sont égales), le widget de message d’erreur est défini surHIDDENet ne s’affiche pas.
Voici l'exemple de code d'application et le fichier manifeste JSON :
Apps Script
function onConfig() {
// Create a Card
let cardBuilder = CardService.newCardBuilder();
const textInput_1 = CardService.newTextInput()
.setTitle("Input field 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 field 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("Enter same values for the two input fields")
.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("<font color=\"#FF0000\"><b>Error:</b> Please enter the same values for both input fields.</font>")
.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": "cel_validation_demo",
"state": "ACTIVE",
"name": "CEL Demo",
"description": "Demonstrates CEL Validation",
"workflowAction": {
"inputs": [
{
"id": "value1",
"description": "The first number",
"cardinality": "SINGLE",
"dataType": {
"basicType": "STRING"
}
},
{
"id": "value2",
"description": "The second number",
"cardinality": "SINGLE",
"dataType": {
"basicType": "STRING"
}
}
],
"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 :
TextInputSelectionInputDateTimePicker
Opérations de validation CEL compatibles
- Opérations arithmétiques
+: ajoute deux nombresint64,uint64oudouble.-: soustrait deux nombresint64,uint64oudouble.*: multiplie deux nombresint64,uint64oudouble./: divise deux nombresint64,uint64oudouble(division entière).%: calcule le modulo de deuxint64ouuint64nombres.-: inverse un nombreint64ouuint64.
- Opérations logiques :
&&: effectue une opération logiqueANDsur deux valeurs booléennes.||: effectue une opération logiqueORsur deux valeurs booléennes.!: effectue une opération logiqueNOTsur 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 nombreint64,uint64oudoubleest inférieur au second.<=: vérifie si le premier nombreint64,uint64oudoubleest inférieur ou égal au second.>: vérifie si le premier nombreint64,uint64oudoubleest supérieur au second.>=: vérifie si le premier nombreint64,uint64oudoubleest supérieur ou égal au second.
- Opérations de liste :
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 dans une liste. Compatible avec les nombres et les listes imbriquées.
Scénarios de validation CEL non compatibles
- Tailles d'arguments incorrectes pour les opérations binaires : les opérations binaires (par exemple,
add_int64, equals) nécessitent exactement deux arguments. Si vous fournissez un nombre d'arguments différent, une erreur sera générée. - Tailles d'arguments incorrectes pour les opérations unaires : les opérations unaires (par exemple,
negate_int64) nécessitent exactement un argument. Si vous fournissez un nombre d'arguments différent, une erreur sera générée. - Types non compatibles dans les opérations numériques : les opérations binaires et unaires numériques 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
Avec la validation côté serveur, vous pouvez exécuter une logique côté serveur en spécifiant onSaveFunction() dans le code de votre étape. Lorsque l'utilisateur quitte la carte de configuration de l'étape, onSaveFunction() s'exécute et vous permet de vérifier l'entrée 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 carte de configuration qui affiche un message d'erreur expliquant à l'utilisateur comment résoudre l'erreur.
Étant donné que la validation côté serveur est asynchrone, l'utilisateur peut ne pas être informé de l'erreur d'entrée tant qu'il n'a pas publié son flux.
L'id de chaque entrée validée dans le fichier manifeste doit correspondre au name d'un widget de carte dans le code.
L'exemple suivant valide qu'une entrée de texte 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": "server_validation_demo",
"state": "ACTIVE",
"name": "Email address validation",
"description": "Asks the user for an email address",
"workflowAction": {
"inputs": [
{
"id": "email",
"description": "email address",
"cardinality": "SINGLE",
"required": true,
"dataType": {
"basicType": "STRING"
}
}
],
"onConfigFunction": "onConfig",
"onExecuteFunction": "onExecute",
"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. Sinon, il renvoie une carte de configuration avec un message d'erreur expliquant comment corriger l'erreur.
Apps Script
// A helper method to push a card interface
function pushCard(card) {
const navigation = AddOnsResponseService.newNavigation()
.pushCard(card);
const action = AddOnsResponseService.newAction()
.addNavigation(navigation);
return AddOnsResponseService.newRenderActionBuilder()
.setAction(action)
.build();
}
function onConfig() {
const emailInput = CardService.newTextInput()
.setFieldName("email")
.setTitle("User e-mail")
.setId("email");
const saveButton = CardService.newTextButton()
.setText("Save!")
.setOnClickAction(
CardService.newAction()
.setFunctionName('onSave')
)
const sections = CardService.newCardSection()
.setHeader("Server-side validation")
.setId("section_1")
.addWidget(emailInput)
.addWidget(saveButton);
let card = CardService.newCardBuilder()
.addSection(sections)
.build();
return pushCard(card);
}
function onExecute(event) {
}
/**
* Validates user input asynchronously when the user
* navigates away from a step's configuration card.
*/
function onSave(event) {
console.log(JSON.stringify(event, null, 2));
// "email" matches the input ID specified in the manifest file.
var email = event.formInputs["email"][0];
console.log(JSON.stringify(email, null, 2));
// Validate that the email address contains an "@" sign:
if (email.includes("@")) {
// If successfully validated, save and proceed.
const hostAppAction = AddOnsResponseService.newHostAppAction()
.setWorkflowAction(
AddOnsResponseService.newSaveWorkflowAction()
);
const textDeletion = AddOnsResponseService.newRemoveWidget()
.setWidgetId("errorMessage");
const modifyAction = AddOnsResponseService.newAction()
.addModifyCard(
AddOnsResponseService.newModifyCard()
.setRemoveWidget(textDeletion)
);
return AddOnsResponseService.newRenderActionBuilder()
.setHostAppAction(hostAppAction)
.setAction(modifyAction)
.build();
} else {
// If the input is invalid, return a card with an error message
const textParagraph = CardService.newTextParagraph()
.setId("errorMessage")
.setMaxLines(1)
.setText("<font color=\"#FF0000\"><b>Error:</b> Email addresses must include the '@' sign.</font>");
const emailInput = CardService.newTextInput()
.setFieldName("email")
.setTitle("User e-mail")
.setId("email");
const saveButton = CardService.newTextButton()
.setText("Save!")
.setOnClickAction(
CardService.newAction().setFunctionName('onSave')
)
const sections = CardService.newCardSection()
.setHeader("Server-side validation")
.setId("section_1")
.addWidget(emailInput)
.addWidget(textParagraph) //Insert the error message
.addWidget(saveButton);
let card = CardService.newCardBuilder()
.addSection(sections)
.build();
const navigation = AddOnsResponseService.newNavigation()
.pushCard(card);
const action = AddOnsResponseService.newAction()
.addNavigation(navigation);
const hostAppAction = AddOnsResponseService.newHostAppAction()
.setWorkflowAction(
AddOnsResponseService.newWorkflowValidationErrorAction()
.setSeverity(AddOnsResponseService.ValidationErrorSeverity.CRITICAL)
);
return AddOnsResponseService.newRenderActionBuilder()
.setHostAppAction(hostAppAction)
.setAction(action)
.build();
}
}
Articles associés
- Définir une variable d'entrée
- Consigner l'activité et les erreurs
- Objets d'événement Workspace Studio
- CEL (Common Expression Language)