En esta guía, se explica cómo validar una variable de entrada.
Cuando definas una variable de entrada, como práctica recomendada, valida que el usuario ingrese un valor adecuado. Por ejemplo, si le pides al usuario que ingrese un
número, verificar que ingrese 1 en lugar de a confirma que el paso
se ejecuta sin errores.
Existen dos formas de validar una variable de entrada:
- Validación del cliente: Con la validación del cliente, verificas la entrada del usuario directamente en su dispositivo. El usuario recibe comentarios inmediatos y puede corregir cualquier error en su entrada mientras configura el paso.
- Validación del servidor: La validación del servidor te permite ejecutar lógica en el servidor durante la validación, lo que es útil cuando necesitas buscar información que el cliente no tiene, como datos en otros sistemas o bases de datos.
Validación del cliente
Existen dos formas de implementar la validación del cliente:
- Para la validación básica, como verificar que un widget contenga menos de una cierta cantidad de caracteres o que contenga el símbolo
@, invoca la claseValidationdel servicio de tarjetas del complemento de Google Workspace. - Para una validación sólida, como comparar valores de widgets con otros valores de widgets, puedes agregar la validación de Common Expression Language (CEL)
a los siguientes widgets de tarjetas compatibles con
CardService.
Invoca la clase Validation
En el siguiente ejemplo, se valida que un widget TextInput contenga 10 caracteres o menos:
Apps Script
const validation = CardService.newValidation().setCharacterLimit('10').setInputType(
CardService.InputType.TEXT);
Para obtener opciones de validación adicionales, usa la validación de CEL.
Validación de CEL
La validación de Common Expression Language (CEL) ofrece verificaciones de entrada instantáneas sin la latencia de la validación del servidor, ya que descarga las verificaciones de valores de entrada que no dependen de la búsqueda de datos de otros servicios al cliente.
También puedes usar CEL para crear comportamientos de tarjetas, como mostrar u ocultar un widget según el resultado de la validación. Este tipo de comportamiento es útil para mostrar u ocultar un mensaje de error que ayuda a los usuarios a corregir sus entradas.
La creación de una validación de CEL completa incluye los siguientes componentes:
ExpressionDataen la tarjeta: Contiene la lógica de validación especificada y la lógica de activación del widget cuando se cumple una de las condiciones definidas.Id: Un identificador único paraExpressionDatadentro de la tarjeta actual.Expression: La cadena CEL que define la lógica de validación (p.ej.,"value1 == value2").Conditions: Una lista de condiciones que contiene una selección de resultados de validación predefinidos (SUCCESS o FAILURE). Las condiciones están vinculadas aEventActiondel widget a través deTriggerscon unactionRuleIdcompartido.EventActiona nivel de la tarjeta: Activa las validaciones de CEL en la tarjeta y asocia el campoExpressionDataa los widgets de resultados a través de activadores posteriores al evento.actionRuleId: Es el ID único de esteEventAction.ExpressionDataAction: Se establece enSTART_EXPRESSION_EVALUATIONpara indicar que esta acción inicia la evaluación de CEL.Trigger: Conecta lasConditionsaEventActionsdel widget según elactionRuleId.
EventActiona nivel del widget: Controla el comportamiento del widget de resultados cuando se cumple la condición de éxito o falla. Por ejemplo, un widget de resultados puede ser unTextParagraphque contiene un mensaje de error que solo se hace visible cuando falla la validación.actionRuleId: Coincide con elactionRuleIden elTriggerdel lado de la tarjeta.CommonWidgetAction: Define acciones que no implican evaluaciones, como actualizar la visibilidad del widget.UpdateVisibilityAction: Es una acción que actualiza el estado de visibilidad de un widget (VISIBLE o HIDDEN).
En el siguiente ejemplo, se muestra cómo implementar la validación de CEL para verificar si dos entradas de texto son iguales. Si no son iguales, se muestra un mensaje de error.
-
Figura 1: Cuando se cumple la failCondition(las entradas no son iguales), el widget del mensaje de error se establece enVISIBLEy aparece. -
Figura 2: Cuando se cumple la successCondition, el widget del mensaje de error se establece enHIDDENy no aparece.
Aquí tienes el código de la aplicación de ejemplo y el archivo de manifiesto 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();
}
Archivo de manifiesto 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 y operaciones de validación de CEL compatibles
Widgets de tarjetas que admiten la validación de CEL
Los siguientes widgets admiten la validación de CEL:
TextInputSelectionInputDateTimePicker
Operaciones de validación de CEL compatibles
- Operaciones aritméticas
+: Agrega dos númerosint64,uint64, odouble.-: Resta dos númerosint64,uint64odouble.*: Multiplica dos númerosint64,uint64odouble./: Divide dos númerosint64,uint64odouble(división de números enteros).%: Calcula el módulo de dosint64ouint64números.-: Niega unint64ouint64número.
- Operaciones lógicas:
&&: Realiza una operación lógicaANDen dos valores booleanos.||: Realiza una operación lógicaORen dos valores booleanos.!: Realiza una operación lógicaNOTen un valor booleano.
- Operaciones de comparación:
==: Verifica si dos valores son iguales. Admite números y listas.!=: Verifica si dos valores no son iguales. Admite números y listas.<: Verifica si el primer númeroint64,uint64odoublees menor que el segundo.<=: Verifica si el primer númeroint64,uint64odoublees menor o igual que el segundo.>: Verifica si el primer númeroint64,uint64odoublees mayor que el segundo.>=: Verifica si el primer númeroint64,uint64odoublees mayor o igual que el segundo.
- Operaciones de lista:
in: Verifica si un valor está presente en una lista. Admite números, cadenas y listas anidadas.size: Muestra la cantidad de elementos de una lista. Admite números y listas anidadas.
Casos de uso de validación de CEL no admitidos
- Tamaños de argumentos incorrectos para operaciones binarias: Las operaciones binarias (por ejemplo,
add_int64, equals) requieren exactamente dos argumentos. Si proporcionas una cantidad diferente de argumentos, se mostrará un error. - Tamaños de argumentos incorrectos para operaciones unarias: Las operaciones unarias (por ejemplo,
negate_int64) requieren exactamente un argumento. Si proporcionas una cantidad diferente de argumentos, se mostrará un error. - Tipos no admitidos en operaciones numéricas: Las operaciones numéricas binarias y unarias solo aceptan argumentos numéricos. Si proporcionas otros tipos (por ejemplo, booleanos), se mostrará un error.
Validación del servidor
Con la validación del servidor, puedes ejecutar la lógica del servidor especificando onSaveFunction() en el código de tu paso. Cuando el usuario sale de la tarjeta de configuración del paso, se ejecuta onSaveFunction() y te permite verificar la entrada del usuario.
Si la entrada del usuario es válida, muestra saveWorkflowAction.
Si la entrada del usuario no es válida, muestra una tarjeta de configuración que muestre un mensaje de error al usuario en el que se explique cómo resolver el error.
Debido a que la validación del servidor es asíncrona, es posible que el usuario no conozca el error de entrada hasta que publique su flujo.
El id de cada entrada validada en el archivo de manifiesto debe coincidir con el name de un widget de tarjeta en el código.
En el siguiente ejemplo, se valida que una entrada de texto del usuario incluya el signo "@":
Archivo de manifiesto
El fragmento del archivo de manifiesto especifica una onSaveFunction() llamada "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 de la aplicación
El código del paso incluye una función llamada onSave(). Valida que una cadena ingresada por el usuario incluya @. Si lo hace, guarda el paso. Si no lo hace, muestra una tarjeta de configuración con un mensaje de error en el que se explica cómo corregir el error.
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
- Cómo definir una variable de entrada
- Cómo registrar la actividad y los errores
- Objetos de eventos de Workspace Studio
- Common Expression Language (CEL)