Weryfikowanie zmiennej wejściowej

Z tego przewodnika dowiesz się, jak sprawdzić poprawność zmiennej wejściowej.

Podczas definiowania zmiennej wejściowej warto sprawdzić, czy użytkownik wpisuje odpowiednią wartość. Jeśli na przykład poprosisz użytkownika o wpisanie cyfry, sprawdzenie, czy wpisze on 1 zamiast a, potwierdzi, że krok działa bez błędów.

Zmienną wejściową możesz sprawdzić na 2 sposoby:

  • Weryfikacja po stronie klienta: weryfikacja po stronie klienta polega na sprawdzaniu danych wprowadzonych przez użytkownika bezpośrednio na jego urządzeniu. Użytkownik od razu otrzymuje informację zwrotną i może poprawić błędy w danych wejściowych podczas konfigurowania kroku.
  • Weryfikacja po stronie serwera: Weryfikacja po stronie serwera umożliwia uruchamianie logiki na serwerze podczas weryfikacji. Jest to przydatne, gdy trzeba wyszukać informacje, których klient nie ma, np. dane w innych systemach lub bazach danych.

Weryfikacja po stronie klienta

Weryfikację po stronie klienta możesz zaimplementować na 2 sposoby:

  • W przypadku podstawowej weryfikacji, np. sprawdzenia, czy widżet zawiera mniej niż określoną liczbę znaków lub czy zawiera symbol @, wywołaj klasę Validationusługi kart dodatku Google Workspace .
  • W przypadku bardziej złożonej weryfikacji, np. porównywania wartości widżetów z innymi wartościami widżetów, możesz dodać weryfikację za pomocą języka CEL (Common Expression Language) do tych obsługiwanych widżetów kart za pomocą CardService.

Wywoływanie klasy Validation

Ten przykład sprawdza, czy widżet TextInput zawiera nie więcej niż 10 znaków:

Apps Script

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

Aby uzyskać dodatkowe opcje weryfikacji, użyj weryfikacji za pomocą języka CEL.

Weryfikacja za pomocą języka CEL

Weryfikacja za pomocą języka CEL (Common Expression Language) umożliwia natychmiastowe sprawdzanie danych wejściowych bez opóźnienia związanego z weryfikacją po stronie serwera. Odbywa się to przez przeniesienie na stronę klienta sprawdzania wartości wejściowych, które nie zależą od wyszukiwania danych z innych usług.

Za pomocą języka CEL możesz też tworzyć zachowania kart, np. wyświetlać lub ukrywać widżet w zależności od wyniku weryfikacji. Tego rodzaju zachowanie jest przydatne do wyświetlania lub ukrywania komunikatu o błędzie, który pomaga użytkownikom poprawić dane wejściowe.

Pełna weryfikacja za pomocą języka CEL obejmuje te komponenty:

  • ExpressionData na karcie: zawiera określoną logikę weryfikacji i logikę wyzwalania widżetu, gdy zostanie spełniony jeden ze zdefiniowanych warunków.

    • Id: unikalny identyfikator ExpressionData na bieżącej karcie.
    • Expression: ciąg tekstowy CEL, który definiuje logikę weryfikacji (np. "value1 == value2").
    • Conditions: lista warunków, która zawiera wybór wstępnie zdefiniowanych wyników weryfikacji (SUCCESS lub FAILURE). Warunki są powiązane z elementem EventAction po stronie widżetu za pomocą elementu Triggers ze wspólnym elementem actionRuleId.
    • EventAction na poziomie karty: aktywuje weryfikacje za pomocą języka CEL na karcie i łączy pole ExpressionData z widżetami wyników za pomocą wyzwalaczy po zdarzeniu.
      • actionRuleId: unikalny identyfikator tego elementu EventAction.
      • ExpressionDataAction: ustaw na START_EXPRESSION_EVALUATION, aby wskazać, że to działanie rozpoczyna ocenę za pomocą języka CEL.
      • Trigger: łączy Conditions z elementami EventActions po stronie widżetu na podstawie elementu actionRuleId.
  • EventAction na poziomie widżetu: kontroluje zachowanie widżetu wyników, gdy zostanie spełniony warunek powodzenia lub niepowodzenia. Widżet wyników może być na przykład elementem TextParagraph, który zawiera komunikat o błędzie widoczny tylko wtedy, gdy weryfikacja się nie powiedzie.

    • actionRuleId: pasuje do elementu actionRuleId w elemencie Trigger po stronie karty.
    • CommonWidgetAction: definiuje działania, które nie obejmują ocen, np. aktualizowanie widoczności widżetu.
      • UpdateVisibilityAction: działanie, które aktualizuje stan widoczności widżetu (VISIBLE lub HIDDEN).

Ten przykład pokazuje, jak zaimplementować weryfikację za pomocą języka CEL, aby sprawdzić, czy 2 pola tekstowe są równe. Jeśli nie są równe, wyświetla się komunikat o błędzie.

  • Gdy warunek failCondition zostanie spełniony (dane wejściowe nie są równe), widżet komunikatu o błędzie zostanie ustawiony na VISIBLE i pojawi się.
    Ilustracja 1: gdy zostanie spełniony warunek failCondition (dane wejściowe nie są równe), widżet komunikatu o błędzie zostanie ustawiony na VISIBLE i pojawi się.
  • Gdy warunek successCondition zostanie spełniony (dane wejściowe są równe), widżet komunikatu o błędzie zostanie ustawiony na HIDDEN i nie będzie się wyświetlać.
    Ilustracja 2: gdy zostanie spełniony warunek successCondition (dane wejściowe są równe), widżet komunikatu o błędzie zostanie ustawiony na HIDDEN i nie pojawi się.

Oto przykładowy kod aplikacji i plik manifestu 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();
}

Plik manifestu 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"
          }
        }
      ]
    }
  }
}

Obsługiwane widżety i operacje weryfikacji za pomocą języka CEL

Widżety kart obsługujące weryfikację za pomocą języka CEL

Te widżety obsługują weryfikację za pomocą języka CEL:

  • TextInput
  • SelectionInput
  • DateTimePicker

Obsługiwane operacje weryfikacji za pomocą języka CEL

  • Operacje arytmetyczne:
    • +: dodaje 2 liczby int64, uint64 lub double.
    • -: odejmuje 2 liczby int64, uint64 lub double.
    • *: mnoży 2 liczby int64, uint64 lub double.
    • /: dzieli 2 liczby int64, uint64 lub double (dzielenie całkowite).
    • %: oblicza modulo 2 liczb int64 lub uint64.
    • -: neguje liczbę int64 lub uint64.
  • Operacje logiczne:
    • &&: wykonuje logiczną operację AND na 2 wartościach logicznych.
    • ||: wykonuje logiczną operację OR na 2 wartościach logicznych.
    • !: wykonuje logiczną operację NOT na wartości logicznej.
  • Operacje porównania:
    • ==: sprawdza, czy 2 wartości są równe. Obsługuje liczby i listy.
    • !=: sprawdza, czy 2 wartości nie są równe. Obsługuje liczby i listy.
    • <: sprawdza, czy pierwsza liczba int64, uint64 lub double jest mniejsza od drugiej.
    • <=: sprawdza, czy pierwsza liczba int64, uint64 lub double jest mniejsza od drugiej lub jej równa.
    • >: sprawdza, czy pierwsza liczba int64, uint64 lub double jest większa od drugiej.
    • >=: sprawdza, czy pierwsza liczba int64, uint64 lub double jest większa od drugiej lub jej równa.
  • Operacje na listach:
    • in: sprawdza, czy wartość jest obecna na liście. Obsługuje liczby, ciągi znaków i listy zagnieżdżone.
    • size: zwraca liczbę elementów na liście. Obsługuje liczby i listy zagnieżdżone.

Nieobsługiwane scenariusze weryfikacji za pomocą języka CEL

  • Nieprawidłowe rozmiary argumentów w przypadku operacji binarnych: operacje binarne (np. add_int64, equals) wymagają dokładnie 2 argumentów. Podanie innej liczby argumentów spowoduje błąd.
  • Nieprawidłowe rozmiary argumentów w przypadku operacji jednoargumentowych: operacje jednoargumentowe (np. negate_int64) wymagają dokładnie 1 argumentu. Podanie innej liczby argumentów spowoduje błąd.
  • Nieobsługiwane typy w operacjach numerycznych: operacje numeryczne binarne i jednoargumentowe akceptują tylko argumenty liczbowe. Podanie innych typów (np. logicznych) spowoduje błąd.

Weryfikacja po stronie serwera

W przypadku weryfikacji po stronie serwera możesz uruchamiać logikę po stronie serwera, określając onSaveFunction() w kodzie kroku. Gdy użytkownik opuści kartę konfiguracji kroku, zostanie uruchomiona funkcja onSaveFunction(), która umożliwi sprawdzenie danych wprowadzonych przez użytkownika.

Jeśli dane wejściowe użytkownika są prawidłowe, zwróć saveWorkflowAction.

Jeśli dane wejściowe użytkownika są nieprawidłowe, zwróć kartę konfiguracji, która wyświetla komunikat o błędzie wyjaśniający, jak rozwiązać problem.

Ponieważ weryfikacja po stronie serwera jest asynchroniczna, użytkownik może nie wiedzieć o błędzie w danych wejściowych, dopóki nie opublikuje przepływu.

Każdy zweryfikowany element id w pliku manifestu musi być zgodny z elementem name widżetu karty w kodzie.

Ten przykład sprawdza, czy dane tekstowe wprowadzone przez użytkownika zawierają znak „@”:

Plik manifestu

Fragment pliku manifestu określa onSaveFunction() o nazwie „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"
          }
        }
      ]
    }
  }
}

Kod aplikacji

Kod kroku zawiera funkcję o nazwie onSave(). Sprawdza ona, czy ciąg znaków wprowadzony przez użytkownika zawiera znak „@”. Jeśli tak, zapisuje krok. Jeśli nie, zwraca kartę konfiguracji z komunikatem o błędzie wyjaśniającym, jak rozwiązać problem.

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