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 Common Expression Language (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 estão vinculadas aoEventActiondo lado do widget por meio deTriggerscom 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.
O exemplo de código e o manifesto JSON a seguir mostram:
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 numéricas binárias e unárias 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 sim, 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
- Variáveis de entrada
- Registrar atividades e erros
- Objetos de evento do Workspace Studio
- Common Expression Language (CEL)