Este guia explica como validar uma variável de entrada.
Ao definir uma variável de entrada, como prática recomendada, valide se o usuário insere um valor adequado. Por exemplo, se você pedir ao usuário para inserir um
numeral, verificar se ele insere 1 em vez de a confirma que a etapa
é executada sem erros.
Há duas maneiras de validar uma variável de entrada:
- Validação do lado do cliente: Com a validação do lado do cliente, você verifica a entrada do usuário diretamente no dispositivo. O usuário recebe feedback imediato e pode corrigir erros na entrada ao configurar a etapa.
- Validação do lado do servidor: a validação do lado do servidor permite executar a lógica no servidor durante a validação, o que é útil quando você precisa pesquisar informações que o cliente não tem, como dados em outros sistemas ou bancos de dados.
Validação do lado do cliente
Há duas maneiras de implementar a validação do lado do cliente:
- Para validação básica, como verificar se um widget contém menos de um determinado número de caracteres ou contém o símbolo
@, invoque a classeValidationdo serviço de card do complemento do Google Workspace. - Para validação robusta, como comparar valores de widget com outros valores de widget, você pode adicionar a validação da Linguagem de expressão comum (CEL)
aos seguintes widgets de card compatíveis usando
CardService.
Invocar a classe Validation
O exemplo a seguir valida se um widget TextInput contém 10 ou menos caracteres:
Apps Script
const validation = CardService.newValidation().setCharacterLimit('10').setInputType(
CardService.InputType.TEXT);
Para outras opções de validação, use a validação CEL.
Validação CEL
A validação da Common Expression Language (CEL) oferece verificações de entrada instantâneas sem a latência da validação do lado do servidor, descarregando as verificações de valor de entrada que não dependem da pesquisa de dados de outros serviços para o lado do cliente.
Você também pode usar a CEL para criar comportamentos de card, como mostrar ou ocultar um widget dependendo do resultado da validação. Esse tipo de comportamento é útil para mostrar ou ocultar uma mensagem de erro que ajuda os usuários a corrigir as entradas.
A criação de uma validação CEL completa envolve os seguintes componentes:
ExpressionDatano card: contém a lógica de validação especificada e a lógica de acionamento do widget quando uma das condições definidas é atendida.Id: um identificador exclusivo para oExpressionDatano card atual.Expression: a string CEL que define a lógica de validação (por exemplo,"value1 == value2").Conditions: uma lista de condições que contém uma seleção de resultados de validação predefinidos (SUCESSO ou FALHA). As condições são vinculadas aoEventActiondo lado do widget porTriggerscom umactionRuleIdcompartilhado.EventActionno nível do card: ativa as validações CEL no card e associa o campoExpressionDataaos widgets de resultado por acionadores pós-evento.actionRuleId: ID exclusivo para esseEventAction.ExpressionDataAction: definido comoSTART_EXPRESSION_EVALUATIONpara indicar que essa ação inicia a avaliação CEL.Trigger: conecta asConditionsaEventActionsdo lado do widget com base noactionRuleId.
EventActionno nível do widget: controla o comportamento do widget de resultado quando a condição de sucesso ou falha é atendida. Um widget de resultado, por exemplo, pode ser umTextParagraphque contém uma mensagem de erro que só fica visível quando a validação falha.actionRuleId: corresponde aoactionRuleIdnoTriggerdo lado do card.CommonWidgetAction: define ações que não envolvem avaliações, como atualizar a visibilidade do widget.UpdateVisibilityAction: uma ação que atualiza o estado de visibilidade de um widget (VISÍVEL ou OCULTO).
O exemplo a seguir demonstra como implementar a validação CEL para verificar se duas entradas de texto são iguais. Uma mensagem de erro será mostrada se elas não forem iguais.
-
Figura 1: Quando a failConditioné atendida (as entradas não são iguais), o widget de mensagem de erro é definido comoVISIBLEe aparece. -
Figura 2: quando a successConditioné atendida (as entradas são iguais), o widget de mensagem de erro é definido comoHIDDENe não aparece.
Confira o exemplo de código do aplicativo e o arquivo de manifesto 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();
}
Arquivo de manifesto 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 e operações de validação CEL compatíveis
Widgets de card que aceitam a validação CEL
Os seguintes widgets aceitam a validação CEL:
TextInputSelectionInputDateTimePicker
Operações de validação CEL compatíveis
- Operações aritméticas
+: adiciona dois númerosint64,uint64oudouble.-: subtrai dois númerosint64,uint64oudouble.*: multiplica dois númerosint64,uint64oudouble./: divide dois númerosint64,uint64, oudouble(divisão inteira).%: calcula o módulo de doisint64ouuint64números.-: nega um númeroint64ouuint64.
- Operações lógicas:
&&: executa uma operação lógicaANDem dois valores booleanos.||: executa uma operação lógicaORem dois valores booleanos.!: executa uma operação lógicaNOTem um valor booleano.
- Operações de comparação:
==: verifica se dois valores são iguais. Aceita números e listas.!=: verifica se dois valores são diferentes. Aceita números e listas.<: verifica se o primeiro númeroint64,uint64oudoubleé menor que o segundo.<=: verifica se o primeiro númeroint64,uint64oudoubleé menor ou igual ao segundo.>: verifica se o primeiro númeroint64,uint64oudoubleé maior que o segundo.>=: verifica se o primeiro númeroint64,uint64oudoubleé maior ou igual ao segundo.
- Operações de lista:
in: verifica se um valor está presente em uma lista. Aceita números, strings e listas aninhadas.size: retorna o número de itens em uma lista. Aceita números e listas aninhadas.
Cenários de validação CEL não aceitos
- Tamanhos de argumentos incorretos para operações binárias: as operações binárias (por exemplo,
add_int64, equals) exigem exatamente dois argumentos. Fornecer um número diferente de argumentos vai gerar um erro. - Tamanhos de argumentos incorretos para operações unárias: as operações unárias (por exemplo,
negate_int64) exigem exatamente um argumento. Fornecer um número diferente de argumentos vai gerar um erro. - Tipos não aceitos em operações numéricas: as operações binárias e unárias numéricas só aceitam argumentos numéricos. Fornecer outros tipos (por exemplo, booleanos) vai gerar um erro.
Validação do lado do servidor
Com a validação do lado do servidor, você pode executar a lógica do lado do servidor especificando a onSaveFunction() no código da etapa. Quando o usuário sai do card de configuração da etapa, onSaveFunction() é executado e permite verificar a entrada do usuário.
Se a entrada do usuário for válida, retorne saveWorkflowAction.
Se a entrada do usuário for inválida, retorne um card de configuração que mostre uma mensagem de erro ao usuário explicando como resolver o erro.
Como a validação do lado do servidor é assíncrona, o usuário pode não saber sobre o erro de entrada até publicar o fluxo.
O id de cada entrada validada no arquivo de manifesto precisa corresponder ao name de um widget de card no código.
O exemplo a seguir valida se uma entrada de texto do usuário inclui o sinal "@":
Arquivo de manifesto
O trecho do arquivo de manifesto especifica uma onSaveFunction() chamada "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"
}
}
]
}
}
}
Código do aplicativo
O código da etapa inclui uma função chamada onSave(). Ela valida se uma string inserida pelo usuário inclui @. Se isso acontecer, ela salva a etapa. Caso contrário, ela retorna um card de configuração com uma mensagem de erro explicando como corrigir o erro.
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();
}
}
Temas relacionados
- Definir uma variável de entrada
- Registrar atividades e erros
- Objetos de evento do Workspace Studio
- Common Expression Language (CEL)