Recopila datos con una variable de entrada

En esta guía, se explica cómo crear una variable de entrada.

Para ejecutarse, los pasos requieren cierta información. Por ejemplo, para enviar un correo electrónico, se requiere una dirección de correo electrónico. Para proporcionarles a los pasos esta información necesaria, define variables de entrada. Una vez definidas, el usuario suele establecer las variables de entrada en la tarjeta de configuración de un paso mientras lo configura.

Define la variable de entrada en dos lugares: el archivo de manifiesto del complemento y el código con una tarjeta de configuración en la que los usuarios pueden ingresar valores para las variables de entrada.

Define la variable de entrada en el archivo de manifiesto

En el archivo de manifiesto, especifica las variables de entrada con el array inputs[]. Cada elemento del array inputs[] tiene estas propiedades:

  • id: Es un identificador único para una variable de entrada. Para permitir que el flujo asocie un elemento de entrada de la tarjeta de configuración con esta variable de entrada, debe coincidir con el nombre del elemento de tarjeta correspondiente.
  • description: Es una descripción de la variable de entrada que se mostrará a los usuarios finales.
  • cardinality: Es la cantidad de valores permitidos. Los valores posibles son:
    • SINGLE: Solo se permite un valor.
  • dataType: Es el tipo de valores aceptados. dataType tiene la propiedad basicType que define el tipo de datos. Estos son algunos de los valores válidos:
    • STRING: Es una cadena alfanumérica.
    • INTEGER: Es un número.
    • TIMESTAMP: Es una marca de tiempo en el formato "milisegundos desde la época de Unix". Por ejemplo, el 27 de noviembre de 2025, a las 16:49:02 UTC, se representa como 1764262142988.
    • BOOLEAN: Es verdadero o falso.
    • EMAIL_ADDRESS: Es una dirección de correo electrónico en el formato dana@example.com.

En el siguiente ejemplo, se definen tres variables de entrada para un paso de calculadora. Las primeras dos variables de entrada son números enteros y la tercera es una operación aritmética.

JSON

{
  "timeZone": "America/Los_Angeles",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "Calculator",
      "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": "calculatorDemo",
          "state": "ACTIVE",
          "name": "Calculate",
          "description": "Asks the user for two values and a math operation, then performs the math operation on the values and outputs the result.",
          "workflowAction": {
            "inputs": [
              {
                "id": "value1",
                "description": "value1",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "INTEGER"
                }
              },
              {
                "id": "value2",
                "description": "value2",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "INTEGER"
                }
              },
              {
                "id": "operation",
                "description": "operation",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "outputs": [
              {
                "id": "result",
                "description": "Calculated result",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "INTEGER"
                }
              }
            ],
            "onConfigFunction": "onConfigCalculate",
            "onExecuteFunction": "onExecuteCalculate"
          }
        }
      ]
    }
  }
}

Define la variable de entrada en el código

El código del paso incluye una función llamada onConfigFunction() que muestra una tarjeta de configuración que define un widget de tarjeta de entrada para cada variable de entrada definida en el array inputs[] del archivo de manifiesto.

Los widgets de entrada definidos en la tarjeta de configuración tienen los siguientes requisitos:

  • El name de cada widget de entrada debe coincidir con el id de su variable de entrada correspondiente en el archivo de manifiesto.
  • La cardinalidad del widget de entrada debe coincidir con la cardinality de la variable de entrada en el archivo de manifiesto.
  • El tipo de datos del widget de entrada debe coincidir con el dataType de la variable de entrada en el archivo de manifiesto. Si la variable de entrada tiene un dataType de número entero, no puede contener una cadena.

Para obtener ayuda para compilar interfaces de tarjetas, consulta una de estas opciones:

En el siguiente ejemplo, se muestra una tarjeta de configuración para cada widget de entrada definido en Define la variable de entrada en el archivo de manifiesto.

Apps Script

/**
* Generates and displays a configuration card for the sample calculation step.
*
* This function creates a card with input fields for two values and a drop-down
* for selecting an arithmetic operation.
*
* The input fields are configured to let the user select outputs from previous
* workflow steps as input values using the `hostAppDataSource` property.
*/
function onConfigCalculate() {
  const firstInput = CardService.newTextInput()
    .setFieldName("value1") // "FieldName" must match an "id" in the manifest file's inputs[] array.
    .setTitle("First Value")
    .setHostAppDataSource(
      CardService.newHostAppDataSource()
        .setWorkflowDataSource(
          CardService.newWorkflowDataSource()
            .setIncludeVariables(true)
        )
    );

  const secondInput = CardService.newTextInput()
    .setFieldName("value2") // "FieldName" must match an "id" in the manifest file's inputs[] array.
    .setTitle("Second Value")
    .setHostAppDataSource(
      CardService.newHostAppDataSource()
        .setWorkflowDataSource(
          CardService.newWorkflowDataSource()
            .setIncludeVariables(true)
        )
    );

  const selectionInput = CardService.newSelectionInput()
    .setTitle("operation")
    .setFieldName("operation") // "FieldName" must match an "id" in the manifest file's inputs[] array.
    .setType(CardService.SelectionInputType.DROPDOWN)
    .addItem("+", "+", false)
    .addItem("-", "-", true)
    .addItem("x", "x", false)
    .addItem("/", "/", false);

  const sections = CardService.newCardSection()
    .setHeader("Action_sample: Calculate")
    .setId("section_1")
    .addWidget(firstInput)
    .addWidget(selectionInput)
    .addWidget(secondInput)

  let card = CardService.newCardBuilder()
    .addSection(sections)
    .build();

  return card;
}

Usa variables de salida de pasos anteriores

Puedes configurar variables de entrada para aceptar variables de salida de pasos anteriores en el flujo de trabajo.

Habilita la selección de variables

Para permitir que los usuarios seleccionen variables de pasos anteriores, usa la propiedad includeVariables en los widgets TextInput y SelectionInput.

Los widgets TextInput y SelectionInput tienen estas funciones específicas de Workspace Studio:

  • includeVariables: Es una propiedad booleana que permite a los usuarios seleccionar variables de pasos anteriores. Para que el selector de variables se muestre en pasos posteriores, el evento inicial y al menos una variable de salida correspondiente deben asignarse a la variable.
  • type: Es un valor enumerado que autocompleta las sugerencias. Los valores admitidos incluyen:
    • USER: Proporciona sugerencias de autocompletar para las personas en los contactos del usuario.
    • SPACE: Proporciona sugerencias de autocompletar para los espacios de Google Chat de los que el usuario es miembro.

Cuando se configuran includeVariables y type, el campo de entrada combina sus experiencias. Los usuarios pueden seleccionar una variable del type coincidente en un menú desplegable y ver sugerencias de autocompletar para ella.

  • Sugerencias de autocompletar para un espacio de Google Chat.
    Figura 4: Un usuario revisa las sugerencias de autocompletar cuando elige un espacio.
  • El menú de variables permite a los usuarios seleccionar variables de salida de pasos anteriores.
    Figura 5: Un usuario selecciona la variable de salida de un paso anterior en el menú desplegable ➕Variables.

Selecciona solo una variable de salida con un menú ampliado

Puedes configurar un SelectionInput widget para permitir que los usuarios seleccionen una sola variable de salida de un paso anterior con un menú ampliado.

Cuando configuras SelectionInputType como OVERFLOW_MENU, el widget funciona como un selector de variables dedicado. A diferencia de usar includeVariables con TextInput, que convierte los valores de las variables en cadenas, OVERFLOW_MENU conserva el tipo de datos original de la variable seleccionada.

Apps Script

const selectionInput = CardService.newSelectionInput()
  .setFieldName("variable_picker_1")
  .setTitle("Variable Picker")
  .setType(
    CardService.SelectionInputType.OVERFLOW_MENU
  );

Permite que los usuarios combinen texto y variables de salida

Puedes configurar TextInput widgets para controlar cómo los usuarios interactúan con el texto y variables de salida mediante setInputMode().

  • RICH_TEXT: Permite que los usuarios combinen texto y variables de salida. El resultado es una sola cadena concatenada.
  • PLAIN_TEXT: Restringe la entrada. Los usuarios pueden escribir texto o seleccionar una sola variable de salida. Si seleccionas una variable, se reemplazará cualquier texto existente. Usa este modo para aplicar tipos de datos específicos definidos en el manifiesto.

En la siguiente imagen, se muestran dos widgets TextInput. El primero está configurado como RICH_TEXT y contiene texto y una variable de salida. El segundo está configurado como PLAIN_TEXT y solo permite una variable de salida.

  • Widgets de entrada de texto configurados como RICH_TEXT y PLAIN_TEXT
    Figura 3: Widgets de entrada de texto configurados como RICH_TEXT y PLAIN_TEXT.

Te recomendamos que establezcas explícitamente el modo de entrada para todos los widgets TextInput.

Este es el archivo de manifiesto para configurar widgets TextInput con diferentes modos de entrada:

JSON

{
  "timeZone": "America/Toronto",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "Text and output variable demo",
      "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "richTextDemo",
          "state": "ACTIVE",
          "name": "Rich Text Demo",
          "description": "Show the difference between rich text and plain text TextInput widgets",
          "workflowAction": {
            "inputs": [
              {
                "id": "value1",
                "description": "First user input",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              },
              {
                "id": "value2",
                "description": "Second user input",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "onConfigFunction": "onConfiguration",
            "onExecuteFunction": "onExecution"
          }
        }
      ]
    }
  }
}

Este es el código para configurar widgets TextInput con diferentes modos de entrada:

Apps Script

function onConfiguration() {
  const input1 = CardService.newTextInput()
    .setFieldName("value1")
    .setId("value1")
    .setTitle("Rich Text")
    .setHostAppDataSource(
      CardService.newHostAppDataSource()
        .setWorkflowDataSource(
          CardService.newWorkflowDataSource()
            .setIncludeVariables(true)
        )
    )
    // Set input mode to RICH_TEXT to allow mixed text and variables.
    .setInputMode(CardService.TextInputMode.RICH_TEXT);

  const input2 = CardService.newTextInput()
    .setFieldName("value2")
    .setId("value2")
    .setTitle("Plain text")
    .setHostAppDataSource(
      CardService.newHostAppDataSource()
        .setWorkflowDataSource(
          CardService.newWorkflowDataSource()
            .setIncludeVariables(true)
        )
    )
    // Set input mode to PLAIN_TEXT to enforce single variable selection.
    .setInputMode(CardService.TextInputMode.PLAIN_TEXT);

  const section = CardService.newCardSection()
    .addWidget(input1)
    .addWidget(input2);

  const card = CardService.newCardBuilder()
    .addSection(section)
    .build();

  return card;
}

function onExecution(e) {
}

Personaliza los botones del selector de variables

Puedes personalizar el botón del selector de variables si configuras el tamaño y la etiqueta del botón.

Tamaño del botón

Para establecer el tamaño del botón, usa setVariableButtonSize() con una de las siguientes enumeraciones VariableButtonSize:

  • UNSPECIFIED: Es el valor predeterminado. El botón es compacto en el panel lateral y de tamaño completo en otros contextos.
  • COMPACT: El botón solo muestra un signo más (+).
  • FULL_SIZE: El botón muestra la etiqueta de texto completa.

Etiqueta del botón

Para establecer el texto del botón, usa setVariableButtonLabel().

Ejemplo: Personalización del selector de variables

En el siguiente ejemplo, se muestra cómo configurar widgets TextInput con diferentes tamaños de botones del selector de variables y una etiqueta personalizada.

  • Se personalizó el botón del selector de variables en la Web.
    Figura 1: Personalización del botón del selector de variables en la Web.
  • Personalización del botón del selector de variables en un panel lateral del complemento.
    Figura 2: Personalización del botón del selector de variables en un panel lateral del complemento.

Este es el archivo de manifiesto para personalizar los botones del selector de variables:

JSON

{
  "timeZone": "America/Los_Angeles",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "oauthScopes": [
    "https://www.googleapis.com/auth/script.locale"
  ],
  "addOns": {
    "common": {
      "name": "Variable button customization",
      "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "variable_picker_customization",
          "state": "ACTIVE",
          "name": "Variable Picker demo",
          "description": "List all possible variable picker customization options",
          "workflowAction": {
            "onConfigFunction": "onUpdateCardConfigFunction",
            "onExecuteFunction": "onUpdateCardExecuteFunction"
          }
        }
      ]
    }
  }
}

Este es el código para personalizar los botones del selector de variables:

Apps Script

function onUpdateCardConfigFunction(event) {
  const textInput1 = CardService.newTextInput()
    .setFieldName("value1")
    .setTitle("Regular variable picker button")
    .setHostAppDataSource(
      CardService.newHostAppDataSource().setWorkflowDataSource(
        CardService.newWorkflowDataSource()
          .setIncludeVariables(true)
          .setVariableButtonSize(CardService.VariableButtonSize.UNSPECIFIED)
      )
    );

  const textInput2 = CardService.newTextInput()
    .setFieldName("value2")
    .setTitle("Size: Unspecified")
    .setHostAppDataSource(
      CardService.newHostAppDataSource().setWorkflowDataSource(
        CardService.newWorkflowDataSource()
          .setIncludeVariables(true)
          .setVariableButtonSize(CardService.VariableButtonSize.UNSPECIFIED)
      )
    );

  const textInput3 = CardService.newTextInput()
    .setFieldName("value3")
    .setTitle("Size: Full size")
    .setHostAppDataSource(
      CardService.newHostAppDataSource().setWorkflowDataSource(
        CardService.newWorkflowDataSource()
          .setIncludeVariables(true)
          .setVariableButtonSize(CardService.VariableButtonSize.FULL_SIZE)
      )
    );

  const textInput4 = CardService.newTextInput()
    .setFieldName("value4")
    .setTitle("Size: Compact")
    .setHostAppDataSource(
      CardService.newHostAppDataSource().setWorkflowDataSource(
        CardService.newWorkflowDataSource()
          .setIncludeVariables(true)
          .setVariableButtonSize(CardService.VariableButtonSize.COMPACT)
      )
    );

  const textInput5 = CardService.newTextInput()
    .setFieldName("value5")
    .setTitle("Custom button label")
    .setHostAppDataSource(
      CardService.newHostAppDataSource().setWorkflowDataSource(
        CardService.newWorkflowDataSource()
          .setIncludeVariables(true)
          .setVariableButtonLabel("New button label!")
      )
    );

  var cardSection = CardService.newCardSection()
    .addWidget(textInput1)
    .addWidget(textInput2)
    .addWidget(textInput3)
    .addWidget(textInput4)
    .addWidget(textInput5)
    .setId("section_1");

  var card = CardService.newCardBuilder().addSection(cardSection).build();

  return card;
}

function onUpdateCardExecuteFunction(event) {
}

Configura el autocompletado de datos de Google Workspace

También puedes propagar sugerencias de autocompletar a partir de datos dentro del entorno de Google Workspace del usuario:

  • Usuarios de Google Workspace: Propaga usuarios dentro de la misma organización de Google Workspace.
  • Espacios de Google Chat: Propaga los espacios de Google Chat de los que el usuario es miembro.

Para configurar esto, establece el PlatformDataSource en el widget SelectionInput y especifica el WorkflowDataSourceType como USER o SPACE.

Apps Script

// User Autocomplete
var multiSelect2 =
  CardService.newSelectionInput()
    .setFieldName("value2")
    .setTitle("User Autocomplete")
    .setType(CardService.SelectionInputType.MULTI_SELECT)
    .setMultiSelectMaxSelectedItems(3)
    .setPlatformDataSource(
      CardService.newPlatformDataSource()
        .setHostAppDataSource(
          CardService.newHostAppDataSource()
            .setWorkflowDataSource(
              CardService.newWorkflowDataSource()
                .setIncludeVariables(true)
                .setType(CardService.WorkflowDataSourceType.USER)
            ))
    );

// Chat Space Autocomplete
var multiSelect3 =
  CardService.newSelectionInput()
    .setFieldName("value3")
    .setTitle("Chat Space Autocomplete")
    .setType(CardService.SelectionInputType.MULTI_SELECT)
    .setMultiSelectMaxSelectedItems(3)
    .setPlatformDataSource(
      CardService.newPlatformDataSource()
        .setHostAppDataSource(
          CardService.newHostAppDataSource()
            .setWorkflowDataSource(
              CardService.newWorkflowDataSource()
                .setIncludeVariables(true)
                .setType(CardService.WorkflowDataSourceType.SPACE)
            ))
    );

Ejemplo: Combinación de tipos de autocompletado

En el siguiente ejemplo, se muestra una función onConfig que crea una tarjeta con tres SelectionInput widgets, lo que demuestra el autocompletado del servidor, del usuario y del espacio:

JSON

{
  "timeZone": "America/Los_Angeles",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "Autocomplete Demo",
      "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "autocomplete_demo",
          "state": "ACTIVE",
          "name": "Autocomplete Demo",
          "description": "Provide autocompletion in input fields",
          "workflowAction": {
            "inputs": [
              {
                "id": "value1",
                "description": "A multi-select field with autocompletion",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "onConfigFunction": "onConfigAutocomplete",
            "onExecuteFunction": "onExecuteAutocomplete"
          }
        }
      ]
    }
  }
}

Apps Script

function onConfigAutocompleteTest(event) {
  // Handle autocomplete request
  if (event.workflow && event.workflow.elementUiAutocomplete) {
    return handleAutocompleteRequest(event);
  }

  // Server-side autocomplete widget
  var multiSelect1 =
    CardService.newSelectionInput()
      .setFieldName("value1")
      .setTitle("Server Autocomplete")
      .setType(CardService.SelectionInputType.MULTI_SELECT)
      .setMultiSelectMaxSelectedItems(3)
      .addDataSourceConfig(
        CardService.newDataSourceConfig()
          .setRemoteDataSource(
            CardService.newAction().setFunctionName('getAutocompleteResults')
          )
      )
      .addDataSourceConfig(
        CardService.newDataSourceConfig()
          .setPlatformDataSource(
            CardService.newPlatformDataSource()
              .setHostAppDataSource(
                CardService.newHostAppDataSource()
                  .setWorkflowDataSource(
                    CardService.newWorkflowDataSource()
                      .setIncludeVariables(true)
                  ))
          )
      );

  // User autocomplete widget
  var multiSelect2 =
    CardService.newSelectionInput()
      .setFieldName("value2")
      .setTitle("User Autocomplete")
      .setType(CardService.SelectionInputType.MULTI_SELECT)
      .setMultiSelectMaxSelectedItems(3)
      .setPlatformDataSource(
        CardService.newPlatformDataSource()
          .setHostAppDataSource(
            CardService.newHostAppDataSource()
              .setWorkflowDataSource(
                CardService.newWorkflowDataSource()
                  .setIncludeVariables(true)
                  .setType(CardService.WorkflowDataSourceType.USER)
              ))
      );

  // Space autocomplete widget
  var multiSelect3 =
    CardService.newSelectionInput()
      .setFieldName("value3")
      .setTitle("Chat Space Autocomplete")
      .setType(CardService.SelectionInputType.MULTI_SELECT)
      .setMultiSelectMaxSelectedItems(3)
      .setPlatformDataSource(
        CardService.newPlatformDataSource()
          .setHostAppDataSource(
            CardService.newHostAppDataSource()
              .setWorkflowDataSource(
                CardService.newWorkflowDataSource()
                  .setIncludeVariables(true)
                  .setType(CardService.WorkflowDataSourceType.SPACE)
              ))
      );

  var sectionBuilder =
    CardService.newCardSection()
      .addWidget(multiSelect1)
      .addWidget(multiSelect2)
      .addWidget(multiSelect3);

  var card =
    CardService.newCardBuilder()
      .addSection(sectionBuilder)
      .build();
  return card;
}

function handleAutocompleteRequest(event) {
  var invokedFunction = event.workflow.elementUiAutocomplete.invokedFunction;
  var query = event.workflow.elementUiAutocomplete.query;

  if (invokedFunction != "getAutocompleteResults" || query == undefined || query == "") {
    return {};
  }

  // Query your data source to get results
  let autocompleteResponse = AddOnsResponseService.newUpdateWidget()
    .addSuggestion(
      query + " option 1",
      query + "_option1",
      false,
      "https://developers.google.com/workspace/add-ons/images/person-icon.png",
      "option 1 bottom text"
    )
    .addSuggestion(
      query + " option 2",
      query + "_option2",
      false,
      "https://developers.google.com/workspace/add-ons/images/person-icon.png",
      "option 2 bottom text"
    ).addSuggestion(
      query + " option 3",
      query + "_option3",
      false,
      "https://developers.google.com/workspace/add-ons/images/person-icon.png",
      "option 3 bottom text"
    );

  const modifyAction = AddOnsResponseService.newAction()
    .addModifyCard(
      AddOnsResponseService.newModifyCard()
        .setUpdateWidget(autocompleteResponse)
    );

  return AddOnsResponseService.newRenderActionBuilder()
    .setAction(modifyAction)
    .build();
}

Valida la variable de entrada

Como práctica recomendada, valida que el usuario ingrese un valor adecuado. Consulta Validar una variable de entrada.