Convalidare una variabile di input

Questa guida spiega come convalidare una variabile di input.

Quando definisci una variabile di input, come best practice, verifica che l'utente inserisca un valore appropriato. Ad esempio, se chiedi all'utente di inserire un numero, la verifica che inserisca 1 anziché a verifica che il passaggio venga eseguito senza errori.

Esistono due modi per convalidare una variabile di input:

  • Convalida lato client: Con la convalida lato client, verifichi l'input dell'utente direttamente sul suo dispositivo. L'utente riceve un feedback immediato e può correggere eventuali errori nell'input durante la configurazione del passaggio.
  • Convalida lato server: La convalida lato server ti consente di eseguire la logica sul server durante la convalida, il che è utile quando devi cercare informazioni che il client non ha, come dati in altri sistemi o database.

Convalida lato client

Esistono due modi per implementare la convalida lato client:

  • Per la convalida di base, ad esempio la verifica che un widget contenga meno di un determinato numero di caratteri o contenga il simbolo @, richiama la classe Validation del servizio Card del componente aggiuntivo Google Workspace.
  • Per una convalida efficace, ad esempio il confronto dei valori dei widget con altri valori dei widget, puoi aggiungere la convalida Common Expression Language (CEL) ai seguenti widget scheda supportati utilizzando CardService.

Richiamare la classe Validation

Il seguente esempio convalida che un widget TextInput contenga 10 o meno caratteri:

Apps Script

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

Per ulteriori opzioni di convalida, utilizza la convalida CEL.

Convalida CEL

La convalida del Common Expression Language (CEL) offre controlli istantanei dell'input senza la latenza della convalida lato server, scaricando i controlli dei valori di input che non dipendono dalla ricerca di dati di altri servizi sul lato client.

Puoi anche utilizzare CEL per creare comportamenti delle schede, ad esempio mostrare o nascondere un widget a seconda del risultato della convalida. Questo tipo di comportamento è utile per mostrare o nascondere un messaggio di errore che aiuta gli utenti a correggere i propri input.

La creazione di una convalida CEL completa prevede i seguenti componenti:

  • ExpressionData nella scheda: contiene la logica di convalida e la logica di attivazione del widget specificate quando viene soddisfatta una delle condizioni definite.

    • Id: un identificatore univoco per ExpressionData all'interno della scheda corrente.
    • Expression: la stringa CEL che definisce la logica di convalida (ad es. "value1 == value2").
    • Conditions: un elenco di condizioni che contiene una selezione di risultati di convalida predefiniti (SUCCESS o FAILURE). Le condizioni sono associate al widget EventAction tramite Triggers con un actionRuleId condiviso.
    • EventAction a livello di scheda: attiva le convalide CEL nella scheda e associa il campo ExpressionData ai widget dei risultati tramite trigger post-evento.
      • actionRuleId: ID univoco per questo EventAction.
      • ExpressionDataAction: impostato su START_EXPRESSION_EVALUATION per indicare che questa azione avvia la valutazione CEL.
      • Trigger: collega Conditions a EventActions lato widget in base a actionRuleId.
  • EventAction a livello di widget: controlla il comportamento del widget dei risultati quando viene soddisfatta la condizione di successo o errore. Un widget dei risultati, ad esempio, può essere un TextParagraph che contiene un messaggio di errore che diventa visibile solo quando la convalida non va a buon fine.

    • actionRuleId: corrisponde a actionRuleId nel Trigger lato scheda.
    • CommonWidgetAction: definisce le azioni che non comportano valutazioni, come l'aggiornamento della visibilità dei widget.
      • UpdateVisibilityAction: un'azione che aggiorna lo stato di visibilità di un widget (VISIBLE o HIDDEN).

L'esempio seguente mostra come implementare la convalida CEL per verificare se due input di testo sono uguali. Se non sono uguali, viene visualizzato un messaggio di errore.

  • Quando la condizione di errore viene soddisfatta (gli input non sono uguali), il widget del messaggio di errore viene impostato su VISIBLE e viene visualizzato.
    Figura 1: quando la failCondition viene soddisfatta (gli input non sono uguali), il widget del messaggio di errore è impostato su VISIBLE e viene visualizzato.
  • Quando la condizione successCondition viene soddisfatta (gli input sono uguali), il widget del messaggio di errore viene impostato su HIDDEN e non viene visualizzato.
    Figura 2: quando viene soddisfatta la condizione successCondition (gli input sono uguali), il widget del messaggio di errore è impostato su HIDDEN e non viene visualizzato.

Ecco il codice dell'applicazione di esempio e il file manifest 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();
}

File manifest 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"
          }
        }
      ]
    }
  }
}

Widget e operazioni di convalida CEL supportati

Widget delle schede che supportano la convalida CEL

I seguenti widget supportano la convalida CEL:

  • TextInput
  • SelectionInput
  • DateTimePicker

Operazioni di convalida CEL supportate

  • Operazioni aritmetiche
    • +: aggiunge due numeri int64, uint64 o double.
    • -: sottrae due numeri int64, uint64 o double.
    • *: moltiplica due numeri int64, uint64 o double.
    • /: divide due numeri int64, uint64 o double (divisione intera).
    • %: calcola il modulo di due numeri int64 o uint64.
    • -: nega un numero int64 o uint64.
  • Operazioni logiche:
    • &&: esegue un'operazione logica AND su due valori booleani.
    • ||: esegue un'operazione logica OR su due valori booleani.
    • !: esegue un'operazione logica NOT su un valore booleano.
  • Operazioni di confronto:
    • ==: verifica se due valori sono uguali. Supporta numeri ed elenchi.
    • !=: verifica se due valori non sono uguali. Supporta numeri ed elenchi.
    • <: verifica se il primo numero int64, uint64 o double è minore del secondo.
    • <=: verifica se il primo numero int64, uint64 o double è minore o uguale al secondo.
    • >: verifica se il primo numero int64, uint64 o double è maggiore del secondo.
    • >=: verifica se il primo numero int64, uint64 o double è maggiore o uguale al secondo.
  • Operazioni list:
    • in: verifica se un valore è presente in un elenco. Supporta numeri, stringhe ed elenchi nidificati.
    • size: Restituisce il numero di elementi in un elenco. Supporta numeri ed elenchi nidificati.

Scenari di convalida CEL non supportati

  • Dimensioni degli argomenti errate per le operazioni binarie: le operazioni binarie (ad esempio add_int64, uguale) richiedono esattamente due argomenti. Se fornisci un numero diverso di argomenti, verrà generato un errore.
  • Dimensioni degli argomenti errate per le operazioni unarie: le operazioni unarie (ad esempio negate_int64) richiedono esattamente un argomento. Se fornisci un numero diverso di argomenti, verrà generato un errore.
  • Tipi non supportati nelle operazioni numeriche: le operazioni numeriche binarie e unarie accettano solo argomenti numerici. Se fornisci altri tipi (ad esempio booleani), verrà generato un errore.

Convalida lato server

Con la convalida lato server, puoi eseguire la logica lato server specificando onSaveFunction() nel codice del passaggio. Quando l'utente esce dalla scheda di configurazione del passaggio, onSaveFunction() viene eseguito e ti consente di verificare l'input dell'utente.

Se l'input dell'utente è valido, restituisci saveWorkflowAction.

Se l'input dell'utente non è valido, restituisci una scheda di configurazione che mostri un messaggio di errore che spiega all'utente come risolvere il problema.

Poiché la convalida lato server è asincrona, l'utente potrebbe non essere a conoscenza dell'errore di input finché non pubblica il flusso.

Ogni id dell'input convalidato nel file manifest deve corrispondere a un name del widget della scheda nel codice.

Il seguente esempio convalida che l'input di testo di un utente includa il simbolo "@":

File manifest

L'estratto del file manifest specifica un onSaveFunction() denominato "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"
          }
        }
      ]
    }
  }
}

Codice dell'applicazione

Il codice del passaggio include una funzione chiamata onSave(). Verifica che una stringa inserita dall'utente includa @. In caso affermativo, salva il passaggio del flusso. In caso contrario, restituisce una scheda di configurazione con un messaggio di errore che spiega come risolvere il problema.

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);
  }
}