Interaktive UI-Elemente zu Karten hinzufügen

Auf dieser Seite wird beschrieben, wie Sie Karten Widgets und UI-Elemente hinzufügen, damit Nutzer mit Ihrer Google Chat-App interagieren können, z. B. indem sie auf einen Button klicken oder Informationen senden.

Chat-Apps können die folgenden Chat-Schnittstellen verwenden, um interaktive Karten zu erstellen:

  • Nachrichten, die eine oder mehrere Karten enthalten.
  • Startseiten: Das ist eine Karte, die auf dem Tab Startseite in Direktnachrichten mit der Chat-App angezeigt wird.
  • Dialogfelder: Das sind Karten, die in einem neuen Fenster über Nachrichten und Startseiten geöffnet werden.

Wenn Nutzer mit Karten interagieren, können Chat-Apps die empfangenen Daten verarbeiten und entsprechend reagieren. Weitere Informationen finden Sie unter Informationen von Google Chat-Nutzern erheben und verarbeiten.


Mit dem Card Builder können Sie Nachrichten und Benutzeroberflächen für Chat-Apps entwerfen und in der Vorschau ansehen:

Card Builder öffnen

Vorbereitung

Eine Google Chat-App, die so konfiguriert ist, dass sie Nutzerinteraktionen empfängt und darauf reagiert. Wenn Sie eine interaktive Chat-App erstellen möchten, führen Sie eine der folgenden Schnellstartanleitungen aus, die auf der App-Architektur basiert, die Sie verwenden möchten:

Button hinzufügen

Das ButtonList-Widget enthält eine Reihe von Schaltflächen. Auf Schaltflächen kann Text, ein Symbol oder beides angezeigt werden. Jede Button unterstützt eine OnClick-Aktion, die ausgeführt wird, wenn Nutzer auf die Schaltfläche klicken. Beispiel:

  • Öffne einen Hyperlink mit OpenLink, um Nutzern zusätzliche Informationen zu geben.
  • Führen Sie eine action aus, die eine benutzerdefinierte Funktion ausführt, z. B. einen API-Aufruf.

Für die Barrierefreiheit unterstützen Schaltflächen Alternativtext.

Button zum Ausführen einer benutzerdefinierten Funktion hinzufügen

Das Folgende ist eine Karte, die aus einem ButtonList-Widget mit zwei Schaltflächen besteht. Über einen Button wird die Entwicklerdokumentation für Google Chat in einem neuen Tab geöffnet. Über die andere Schaltfläche wird eine benutzerdefinierte Funktion namens goToView() ausgeführt und der Parameter viewType="BIRD EYE VIEW" übergeben.

Button mit Material Design-Stil hinzufügen

Im Folgenden sehen Sie eine Reihe von Schaltflächen in verschiedenen Material Design-Schaltflächenstilen.

Wenn Sie den Material Design-Stil anwenden möchten, dürfen Sie das Attribut „color“ nicht angeben.

Schaltfläche mit benutzerdefinierter Farbe und deaktivierte Schaltfläche hinzufügen

Sie können verhindern, dass Nutzer auf eine Schaltfläche klicken, indem Sie "disabled": "true" festlegen.

Im Folgenden sehen Sie eine Karte, die aus einem ButtonList-Widget mit zwei Schaltflächen besteht. Bei einem Button wird das Feld Color verwendet, um die Hintergrundfarbe des Buttons anzupassen. Der andere Button wird mit dem Feld Disabled deaktiviert, sodass der Nutzer nicht darauf klicken und die Funktion ausführen kann.

Button mit Symbol hinzufügen

Im Folgenden sehen Sie eine Karte, die aus einem ButtonList-Widget mit zwei Button-Symbol-Widgets besteht. Bei einem Button wird das Feld knownIcon verwendet, um das integrierte E‑Mail-Symbol von Google Chat anzuzeigen. Für die andere Schaltfläche wird das Feld iconUrl verwendet, um ein benutzerdefiniertes Symbol-Widget anzuzeigen.

Button mit Symbol und Text hinzufügen

Im Folgenden sehen Sie eine Karte mit einem ButtonList-Widget, das den Nutzer auffordert, eine E‑Mail zu senden. Auf dem ersten Button wird ein E‑Mail-Symbol und auf dem zweiten Button Text angezeigt. Der Nutzer kann entweder auf das Symbol oder auf die Schaltfläche mit dem Text klicken, um die Funktion sendEmail auszuführen.

Schaltfläche für einen minimierbaren Bereich anpassen

Sie können die Steuerungsschaltfläche anpassen, mit der Abschnitte in einer Karte minimiert und maximiert werden. Sie können aus einer Reihe von Symbolen oder Bildern auswählen, um den Inhalt des Abschnitts visuell darzustellen. So können Nutzer die Informationen leichter verstehen und mit ihnen interagieren.

Dreipunkt-Menü hinzufügen

Das Dreipunkt-Menü Overflow menu kann in Chatkarten verwendet werden, um zusätzliche Optionen und Aktionen anzubieten. So können Sie mehr Optionen einfügen, ohne die Benutzeroberfläche der Karte zu überladen, und für ein übersichtliches Design sorgen.

Chip-Liste hinzufügen

Das ChipList-Widget bietet eine vielseitige und visuell ansprechende Möglichkeit, Informationen darzustellen. Verwenden Sie Chiplisten, um Tags, Kategorien oder andere relevante Daten darzustellen. So können Nutzer leichter mit Ihren Inhalten interagieren.

Informationen von Nutzern erheben

In diesem Abschnitt wird beschrieben, wie Sie Widgets hinzufügen, mit denen Informationen wie Text oder Auswahlmöglichkeiten erfasst werden.

Informationen dazu, wie Sie die Eingaben von Nutzern verarbeiten, finden Sie unter Informationen von Google Chat-Nutzern erheben und verarbeiten.

Text erfassen

Das TextInput-Widget bietet ein Feld, in das Nutzer Text eingeben können. Das Widget unterstützt Vorschläge, die Nutzern helfen, einheitliche Daten einzugeben, und On-Change-Aktionen, die Actions sind und ausgeführt werden, wenn sich das Texteingabefeld ändert, z. B. wenn ein Nutzer Text hinzufügt oder löscht.

Wenn Sie abstrakte oder unbekannte Daten von Nutzern erheben müssen, verwenden Sie dieses TextInput-Widget. Wenn Sie definierte Daten von Nutzern erfassen möchten, verwenden Sie stattdessen das SelectionInput-Widget.

Das Folgende ist eine Karte, die aus einem TextInput-Widget besteht:

Datumsangaben oder Uhrzeiten erfassen

Mit dem DateTimePicker-Widget können Nutzer ein Datum, eine Uhrzeit oder beides eingeben. Alternativ können Nutzer mit der Auswahl Daten und Uhrzeiten auswählen. Wenn Nutzer ein ungültiges Datum oder eine ungültige Uhrzeit eingeben, wird im Picker eine Fehlermeldung angezeigt, in der sie aufgefordert werden, die Informationen richtig einzugeben.

Im Folgenden sehen Sie eine Karte mit drei verschiedenen Arten von DateTimePicker-Widgets:

Nutzern erlauben, Elemente auszuwählen

Das SelectionInput-Widget bietet eine Reihe von auswählbaren Elementen wie Kästchen, Optionsfelder, Schalter oder ein Drop-down-Menü. Mit diesem Widget können Sie definierte und standardisierte Daten von Nutzern erheben. Wenn Sie nicht definierte Daten von Nutzern erheben möchten, verwenden Sie stattdessen das TextInput-Widget.

Das SelectionInput-Widget unterstützt Vorschläge, die Nutzern helfen, einheitliche Daten einzugeben, und On-Change-Aktionen, die Actions sind und ausgeführt werden, wenn sich ein Auswahl-Eingabefeld ändert, z. B. wenn ein Nutzer ein Element auswählt oder die Auswahl aufhebt.

Chat-Apps können den Wert ausgewählter Elemente empfangen und verarbeiten. Weitere Informationen zum Arbeiten mit Formulareingaben finden Sie unter Von Nutzern eingegebene Informationen verarbeiten.

In diesem Abschnitt finden Sie Beispiele für Karten, die das SelectionInput-Widget verwenden. In den Beispielen werden verschiedene Arten von Abschnittseingaben verwendet:

Kästchen hinzufügen

Im Folgenden sehen Sie eine Karte, auf der der Nutzer aufgefordert wird, anzugeben, ob ein Kontakt beruflich, privat oder beides ist. Dazu wird ein SelectionInput-Widget mit Kästchen verwendet:

Optionsfeld hinzufügen

Unten sehen Sie eine Karte, auf der der Nutzer aufgefordert wird, anzugeben, ob ein Kontakt beruflich oder privat ist. Dazu wird ein SelectionInput-Widget mit Optionsfeldern verwendet:

Schalter hinzufügen

Im Folgenden sehen Sie eine Karte, auf der der Nutzer aufgefordert wird, anzugeben, ob ein Kontakt beruflich, privat oder beides ist. Dazu wird ein SelectionInput-Widget mit Schaltern verwendet:

Im Folgenden sehen Sie eine Karte, auf der der Nutzer aufgefordert wird, anzugeben, ob ein Kontakt beruflich oder privat ist. Dazu wird ein SelectionInput-Widget mit einem Drop-down-Menü verwendet:

Drop-down-Menüs dynamisch befüllen

Für Google Chat-Apps verfügbar.

Sie können Elemente für ein Drop-down-Menü dynamisch aus Datenquellen in Google Workspace oder aus einer externen Datenquelle einfügen. Wenn Sie dynamische Datenquellen verwenden möchten, geben Sie das Feld data_source_configs an. Das ist ein Array von DataSourceConfig-Objekten. Jedes DataSourceConfig kann entweder ein platformDataSource oder ein remoteDataSource enthalten. Derzeit wird nur ein DataSourceConfig unterstützt.

Elemente aus Google Workspace einfügen

Wenn Sie Elemente aus Google Workspace-Datenquellen wie Google Workspace-Nutzern einfügen möchten, geben Sie das Feld platformDataSource in einem DataSourceConfig an. Im Gegensatz zur Verwendung statischer items lassen Sie SelectionItem-Objekte weg, da diese Auswahlmöglichkeiten dynamisch aus Google Workspace stammen.

Der folgende Code zeigt ein Drop-down-Menü, in dem Google Workspace-Nutzer angezeigt werden:

JSON

{
  "sections": [
    {
      "header": "Section Header",
      "widgets": [
        {
          "selectionInput": {
            "name": "contacts",
            "type": "DROPDOWN",
            "label": "Select contact from organization",
            "data_source_configs": [
              {
                "platformDataSource": {
                  "commonDataSource": "USER"
                },
                "min_characters_trigger": 1
              }
            ]
          }
        }
      ]
    }
  ]
}
Elemente aus einer externen Datenquelle einfügen

Wenn Sie Elemente aus einer Drittanbieter- oder externen Datenquelle wie einem CRM-System (Customer Relationship Management) einfügen möchten, verwenden Sie das Feld remoteDataSource in einem DataSourceConfig, um eine Funktion anzugeben, die Elemente aus der Datenquelle zurückgibt.

Im folgenden Code sehen Sie ein Drop-down-Menü, in dem Elemente aus einer externen Kontaktgruppe angezeigt werden, indem die Funktion getCrmLeads ausgeführt wird:

JSON

{
  "sections": [
    {
      "header": "Section Header",
      "widgets": [
        {
          "selectionInput": {
            "name": "crm_leads",
            "type": "DROPDOWN",
            "label": "Select CRM Lead",
            "data_source_configs": [
              {
                "remoteDataSource": {
                  "function": "getCrmLeads"
                },
                "min_characters_trigger": 2
              }
            ],
            "items": [
              {
                "text": "Suggested Lead 1",
                "value": "lead-1"
              }
            ]
          }
        }
      ]
    }
  ]
}

Um die Anzahl der Anfragen an eine dynamische Datenquelle zu reduzieren, können Sie vorgeschlagene Elemente einfügen, die im Drop-down-Menü angezeigt werden, bevor Nutzer etwas eingeben. Sie können das Drop-down-Menü auch so konfigurieren, dass Elemente automatisch vervollständigt werden, wenn Nutzer etwas eingeben. Dazu legen Sie min_characters_trigger innerhalb von DataSourceConfig fest. Wenn ein Nutzer mindestens die in min_characters_trigger angegebene Anzahl von Zeichen eingibt, wird die in remoteDataSource angegebene Funktion ausgelöst. Das Ereignisobjekt, das an Ihre Funktion übergeben wird, enthält die Eingabe des Nutzers im Schlüssel autocomplete_widget_query.

Multiselect-Menü hinzufügen

Im Folgenden sehen Sie eine Karte, in der der Nutzer aufgefordert wird, Kontakte aus einem Menü mit Mehrfachauswahl auszuwählen:

Sie können Elemente für ein Mehrfachauswahlmenü aus den folgenden Datenquellen in Google Workspace einfügen:

  • Google Workspace-Nutzer: Sie können nur Nutzer innerhalb derselben Google Workspace-Organisation hinzufügen.
  • Chatbereiche: Der Nutzer, der Elemente in das Menü mit Mehrfachauswahl eingibt, kann nur Bereiche ansehen und auswählen, denen er in seiner Google Workspace-Organisation angehört.

Wenn Sie Google Workspace-Datenquellen verwenden möchten, geben Sie das Feld platformDataSource an. Im Gegensatz zu anderen Auswahl-Eingabetypen lassen Sie SelectionItem-Objekte weg, da diese Auswahlmöglichkeiten dynamisch aus Google Workspace stammen.

Im folgenden Code sehen Sie ein Menü mit Mehrfachauswahl für Google Workspace-Nutzer. Um Nutzer zu erfassen, wird durch die Auswahl von commonDataSource der Wert USER festgelegt:

JSON

{
  "selectionInput": {
    "name": "contacts",
    "type": "MULTI_SELECT",
    "label": "Selected contacts",
    "multiSelectMaxSelectedItems": 5,
    "multiSelectMinQueryLength": 1,
    "platformDataSource": {
      "commonDataSource": "USER"
    }
  }
}

Der folgende Code zeigt ein Mehrfachauswahlmenü mit Chatbereichen. Zum Ausfüllen von Leerzeichen wird im Auswahl-Input das Feld hostAppDataSource angegeben. Im Menü für die Mehrfachauswahl wird auch defaultToCurrentSpace auf true gesetzt. Dadurch wird der aktuelle Bereich zur Standardauswahl im Menü:

JSON

{
  "selectionInput": {
    "name": "spaces",
    "type": "MULTI_SELECT",
    "label": "Selected contacts",
    "multiSelectMaxSelectedItems": 3,
    "multiSelectMinQueryLength": 1,
    "platformDataSource": {
      "hostAppDataSource": {
        "chatDataSource": {
          "spaceDataSource": {
            "defaultToCurrentSpace": true
          }
        }
      }
    }
  }
}

In Menüs mit Mehrfachauswahl können auch Elemente aus einer Drittanbieter- oder externen Datenquelle eingefügt werden. Sie können beispielsweise Mehrfachauswahlmenüs verwenden, damit ein Nutzer aus einer Liste von Vertriebs-Leads aus einem CRM-System (Customer Relationship Management) auswählen kann.

Wenn Sie eine externe Datenquelle verwenden möchten, geben Sie im Feld externalDataSource eine Funktion an, die Elemente aus der Datenquelle zurückgibt.

Um die Anzahl der Anfragen an eine externe Datenquelle zu reduzieren, können Sie vorgeschlagene Elemente einfügen, die im Mehrfachauswahlmenü angezeigt werden, bevor Nutzer etwas eingeben. Sie können beispielsweise Kontakte, nach denen der Nutzer vor Kurzem gesucht hat, automatisch ausfüllen. Wenn Sie Vorschläge aus einer externen Datenquelle generieren möchten, geben Sie SelectionItem-Objekte an.

Das folgende Codebeispiel zeigt ein Menü mit Mehrfachauswahl, in dem Elemente aus einer externen Datenquelle abgefragt und eingefügt werden:

Node.js

node/chat/selection-input/index.js
selectionInput: {
  name: "contacts",
  type: "MULTI_SELECT",
  label: "Selected contacts",
  multiSelectMaxSelectedItems: 3,
  multiSelectMinQueryLength: 1,
  externalDataSource: { function: FUNCTION_URL },
  // Suggested items loaded by default.
  // The list is static here but it could be dynamic.
  items: [getSuggestedContact("3")]
}

Ersetzen Sie FUNCTION_URL durch den HTTP-Endpunkt, mit dem die externe Datenquelle abgefragt wird.

Python

python/chat/selection-input/main.py
'selectionInput': {
  'name': "contacts",
  'type': "MULTI_SELECT",
  'label': "Selected contacts",
  'multiSelectMaxSelectedItems': 3,
  'multiSelectMinQueryLength': 1,
  'externalDataSource': { 'function': FUNCTION_URL },
  # Suggested items loaded by default.
  # The list is static here but it could be dynamic.
  'items': [get_suggested_contact("3")]
}

Ersetzen Sie FUNCTION_URL durch den HTTP-Endpunkt, mit dem die externe Datenquelle abgefragt wird.

Java

java/chat/selection-input/src/main/java/com/google/chat/selectionInput/App.java
.setSelectionInput(new GoogleAppsCardV1SelectionInput()
  .setName("contacts")
  .setType("MULTI_SELECT")
  .setLabel("Selected contacts")
  .setMultiSelectMaxSelectedItems(3)
  .setMultiSelectMinQueryLength(1)
  .setExternalDataSource(new GoogleAppsCardV1Action().setFunction(FUNCTION_URL))
  // Suggested items loaded by default.
  // The list is static here but it could be dynamic.
  .setItems(List.of(getSuggestedContact("3")))))))))));

Ersetzen Sie FUNCTION_URL durch den HTTP-Endpunkt, mit dem die externe Datenquelle abgefragt wird.

Apps Script

In diesem Beispiel wird eine Kartenmitteilung gesendet, indem Karten-JSON zurückgegeben wird. Sie können auch den Apps Script-Kartendienst verwenden.

apps-script/chat/selection-input/selection-input.gs
selectionInput: {
  name: "contacts",
  type: "MULTI_SELECT",
  label: "Selected contacts",
  multiSelectMaxSelectedItems: 3,
  multiSelectMinQueryLength: 1,
  externalDataSource: { function: "queryContacts" },
  // Suggested items loaded by default.
  // The list is static here but it could be dynamic.
  items: [getSuggestedContact("3")]
}

Vorschläge aus einer dynamischen Datenquelle generieren

Bei externen Datenquellen können Sie auch Elemente automatisch vervollständigen und vorschlagen, die Nutzer in ein Mehrfachauswahlmenü oder Drop-down-Menü eingeben. Wenn ein Nutzer beispielsweise Atl für ein Menü eingibt, in dem Städte in den USA angezeigt werden, kann Ihre Chat-App Atlanta automatisch vorschlagen, bevor der Nutzer die Eingabe abgeschlossen hat. Sie können bis zu 100 Artikel vorschlagen.

Damit vorgeschlagene Elemente zurückgegeben werden, muss die Funktion, mit der die externe Datenquelle abgefragt wird, Folgendes ausführen:

  1. Verarbeiten Sie ein Ereignisobjekt, das die Chat-App empfängt, wenn Nutzer in das Menü eingeben.
  2. Rufen Sie aus dem Ereignisobjekt den Wert ab, den der Nutzer eingibt. Er wird im Feld event.commonEventObject.parameters["autocomplete_widget_query"] dargestellt.
  3. Fragen Sie die Datenquelle mit dem Nutzereingabewert ab, um ein oder mehrere SelectionItems zu erhalten, die dem Nutzer vorgeschlagen werden können.
  4. Geben Sie vorgeschlagene Elemente zurück, indem Sie die Aktion RenderActions mit einem modifyCard-Objekt zurückgeben.

Das folgende Codebeispiel zeigt, wie eine Chat-App Elemente im Mehrfachauswahlmenü auf einer Karte dynamisch vorschlägt. Wenn ein Nutzer etwas in das Menü eingibt, wird mit der Funktion oder dem Endpunkt, der im Feld externalDataSource des Widgets angegeben ist, eine externe Datenquelle abgefragt und es werden Elemente vorgeschlagen, die der Nutzer auswählen kann:

Node.js

node/chat/selection-input/index.js
/**
 * Web app that responds to events sent from a Google Chat space.
 *
 * @param {Object} req Request sent from Google Chat space
 * @param {Object} res Response to send back
 */
app.post('/', async (req, res) => {
  // Stores the Google Chat event
  const chatEvent = req.body.chat;

  // Handle user interaction with multiselect.
  if(chatEvent.widgetUpdatedPayload) {
    return res.json(queryContacts(req.body));
  }

  // Replies with a card that contains the multiselect menu.
  return res.json({ hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
    cardsV2: [{
      cardId: "contactSelector",
      card: { sections:[{ widgets: [{
        selectionInput: {
          name: "contacts",
          type: "MULTI_SELECT",
          label: "Selected contacts",
          multiSelectMaxSelectedItems: 3,
          multiSelectMinQueryLength: 1,
          externalDataSource: { function: FUNCTION_URL },
          // Suggested items loaded by default.
          // The list is static here but it could be dynamic.
          items: [getSuggestedContact("3")]
        }
      }]}]}
    }]
  }}}}});
});

/**
 * Get contact suggestions based on text typed by users.
 *
 * @param {Object} event the event object that contains the user's query
 * @return {Object} suggestions
 */
function queryContacts(event) {
  const query = event.commonEventObject.parameters["autocomplete_widget_query"];
  return { action: { modifyOperations: [{ updateWidget: { selectionInputWidgetSuggestions: { suggestions: [
    // The list is static here but it could be dynamic.
    getSuggestedContact("1"), getSuggestedContact("2"), getSuggestedContact("3"), getSuggestedContact("4"), getSuggestedContact("5")
  // Only return items based on the query from the user.
  ].filter(e => !query || e.text.includes(query)) }}}]}};
}

/**
 * Generate a suggested contact given an ID.
 *
 * @param {String} id The ID of the contact to return.
 * @return {Object} The contact formatted as a selection item in the menu.
 */
function getSuggestedContact(id) {
  return {
    value: id,
    startIconUri: "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
    text: "Contact " + id
  };
}

Ersetzen Sie FUNCTION_URL durch den HTTP-Endpunkt, mit dem die externe Datenquelle abgefragt wird.

Python

python/chat/selection-input/main.py
@app.route('/', methods=['POST'])
def post() -> Mapping[str, Any]:
  """Handle requests from Google Chat

  Returns:
      Mapping[str, Any]: The response
  """
  # Stores the Google Chat event
  chatEvent = request.get_json().get('chat')

  # Handle user interaction with multiselect.
  if chatEvent.get('widgetUpdatedPayload') is not None:
    return json.jsonify(query_contacts(request.get_json()))

  # Replies with a card that contains the multiselect menu.
  return json.jsonify({ 'hostAppDataAction': { 'chatDataAction': { 'createMessageAction': {
    'message': { 'cardsV2': [{
      'cardId': "contactSelector",
      'card': { 'sections':[{ 'widgets': [{
        'selectionInput': {
          'name': "contacts",
          'type': "MULTI_SELECT",
          'label': "Selected contacts",
          'multiSelectMaxSelectedItems': 3,
          'multiSelectMinQueryLength': 1,
          'externalDataSource': { 'function': FUNCTION_URL },
          # Suggested items loaded by default.
          # The list is static here but it could be dynamic.
          'items': [get_suggested_contact("3")]
        }
      }]}]}
    }]}
  }}}})


def query_contacts(event: dict) -> dict:
  """Get contact suggestions based on text typed by users.

  Args:
      event (Mapping[str, Any]): The event object that contains the user's query

  Returns:
      Mapping[str, Any]: The response with contact suggestions.
  """
  query = event.get("commonEventObject").get("parameters").get("autocomplete_widget_query")
  return { 'action': { 'modifyOperations': [{ 'updateWidget': { 'selectionInputWidgetSuggestions': { 'suggestions': list(
    filter(lambda e: query is None or query in e["text"], [
      # The list is static here but it could be dynamic.
      get_suggested_contact("1"), get_suggested_contact("2"), get_suggested_contact("3"), get_suggested_contact("4"), get_suggested_contact("5")
    # Only return items based on the query from the user
    ])
  )}}}]}}


def get_suggested_contact(id: str) -> dict:
  """Generate a suggested contact given an ID.

  Args:
      id (str): The ID of the contact to return.

  Returns:
      Mapping[str, Any]: The contact formatted as a selection item in the menu.
  """
  return {
    'value': id,
    'startIconUri': "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
    'text': "Contact " + id
  }

Ersetzen Sie FUNCTION_URL durch den HTTP-Endpunkt, mit dem die externe Datenquelle abgefragt wird.

Java

java/chat/selection-input/src/main/java/com/google/chat/selectionInput/App.java
@SpringBootApplication
@RestController
// Web app that responds to events sent from a Google Chat space.
public class App {
  private static final String FUNCTION_URL = "your-function-url";

  public static void main(String[] args) {
    SpringApplication.run(App.class, args);
  }

  /**
   * Handle requests from Google Chat
   * 
   * @param event the event object sent by Google Chat
   * @return The response to be sent back to Google Chat
   */
  @PostMapping("/")
  @ResponseBody
  public GenericJson onEvent(@RequestBody JsonNode event) throws Exception {
    // Stores the Google Chat event
    JsonNode chatEvent = event.at("/chat");

    // Handle user interaction with multiselect.
    if (!chatEvent.at("/widgetUpdatedPayload").isEmpty()) {
      return queryContacts(event);
    }

    // Replies with a card that contains the multiselect menu.
    Message message = new Message().setCardsV2(List.of(new CardWithId()
      .setCardId("contactSelector")
      .setCard(new GoogleAppsCardV1Card()
        .setSections(List.of(new GoogleAppsCardV1Section().setWidgets(List.of(new GoogleAppsCardV1Widget()
          .setSelectionInput(new GoogleAppsCardV1SelectionInput()
            .setName("contacts")
            .setType("MULTI_SELECT")
            .setLabel("Selected contacts")
            .setMultiSelectMaxSelectedItems(3)
            .setMultiSelectMinQueryLength(1)
            .setExternalDataSource(new GoogleAppsCardV1Action().setFunction(FUNCTION_URL))
            // Suggested items loaded by default.
            // The list is static here but it could be dynamic.
            .setItems(List.of(getSuggestedContact("3")))))))))));

    return new GenericJson() {{
      put("hostAppDataAction", new GenericJson() {{
        put("chatDataAction", new GenericJson() {{
          put("createMessageAction", new GenericJson() {{
            put("message", message);
          }});
        }});
      }});
    }};
  }

  /**
   * Get contact suggestions based on text typed by users.
   *
   * @param event the event object that contains the user's query.
   * @return The response with contact suggestions.
   */
  GenericJson queryContacts(JsonNode event) throws Exception {
    String query = event.at("/commonEventObject/parameters/autocomplete_widget_query").asText();
    List<GoogleAppsCardV1SelectionItem> suggestions = List.of(
      // The list is static here but it could be dynamic.
      getSuggestedContact("1"), getSuggestedContact("2"), getSuggestedContact("3"), getSuggestedContact("4"), getSuggestedContact("5")
    // Only return items based on the query from the user
    ).stream().filter(e -> query == null || e.getText().indexOf(query) > -1).toList();

    return new GenericJson() {{
      put("action", new GenericJson() {{
        put("modifyOperations", List.of(new GenericJson() {{
          put("updateWidget", new GenericJson() {{
            put("selectionInputWidgetSuggestions", new GenericJson() {{
              put("suggestions", suggestions);
            }});
          }});
        }}));
      }});
    }};
  }

  /**
   * Generate a suggested contact given an ID.
   * 
   * @param id The ID of the contact to return.
   * @return The contact formatted as a selection item in the menu.
   */
  GoogleAppsCardV1SelectionItem getSuggestedContact(String id) {
    return new GoogleAppsCardV1SelectionItem()
      .setValue(id)
      .setStartIconUri("https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png")
      .setText("Contact " + id);
  }
}

Ersetzen Sie FUNCTION_URL durch den HTTP-Endpunkt, mit dem die externe Datenquelle abgefragt wird.

Apps Script

In diesem Beispiel wird eine Kartenmitteilung gesendet, indem Karten-JSON zurückgegeben wird. Sie können auch den Apps Script-Kartendienst verwenden.

apps-script/chat/selection-input/selection-input.gs
/**
* Responds to a Message trigger in Google Chat.
*
* @param {Object} event the event object from Google Chat
* @return {Object} Response from the Chat app.
*/
function onMessage(event) {
  // Replies with a card that contains the multiselect menu.
  return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
    cardsV2: [{
      cardId: "contactSelector",
      card: { sections:[{ widgets: [{
        selectionInput: {
          name: "contacts",
          type: "MULTI_SELECT",
          label: "Selected contacts",
          multiSelectMaxSelectedItems: 3,
          multiSelectMinQueryLength: 1,
          externalDataSource: { function: "queryContacts" },
          // Suggested items loaded by default.
          // The list is static here but it could be dynamic.
          items: [getSuggestedContact("3")]
        }
      }]}]}
    }]
  }}}}};
}

/**
* Get contact suggestions based on text typed by users.
*
* @param {Object} event the event object that contains the user's query
* @return {Object} suggestions
*/
function queryContacts(event) {
  const query = event.commonEventObject.parameters["autocomplete_widget_query"];
  return { action: { modifyOperations: [{ updateWidget: { selectionInputWidgetSuggestions: { suggestions: [
    // The list is static here but it could be dynamic.
    getSuggestedContact("1"), getSuggestedContact("2"), getSuggestedContact("3"), getSuggestedContact("4"), getSuggestedContact("5")
  // Only return items based on the query from the user.
  ].filter(e => !query || e.text.includes(query)) }}}]}};
}

/**
* Generate a suggested contact given an ID.
*
* @param {String} id The ID of the contact to return.
* @return {Object} The contact formatted as a selection item in the menu.
*/
function getSuggestedContact(id) {
  return {
    value: id,
    startIconUri: "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
    text: "Contact " + id
  };
}

In Karten eingegebene Daten validieren

Auf dieser Seite wird beschrieben, wie Sie Daten validieren, die in die action und die Widgets einer Karte eingegeben werden. Sie können beispielsweise prüfen, ob in ein Texteingabefeld Text eingegeben wurde oder ob es eine bestimmte Anzahl von Zeichen enthält.

Erforderliche Widgets für Aktionen festlegen

Fügen Sie im Rahmen der action der Karte die Namen der Widgets hinzu, die für eine Aktion in der Liste requiredWidgets erforderlich sind.

Wenn für eines der hier aufgeführten Widgets kein Wert vorhanden ist, wenn diese Aktion aufgerufen wird, wird die Formularaktion abgebrochen.

Wenn "all_widgets_are_required": "true" für eine Aktion festgelegt ist, sind alle Widgets auf der Karte für diese Aktion erforderlich.

all_widgets_are_required-Aktion in der Mehrfachauswahl festlegen

JSON

{
  "sections": [
    {
      "header": "Select contacts",
      "widgets": [
        {
          "selectionInput": {
            "type": "MULTI_SELECT",
            "label": "Selected contacts",
            "name": "contacts",
            "multiSelectMaxSelectedItems": 3,
            "multiSelectMinQueryLength": 1,
            "onChangeAction": {
              "all_widgets_are_required": true
            },
            "items": [
              {
                "value": "contact-1",
                "startIconUri": "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
                "text": "Contact 1",
                "bottomText": "Contact one description",
                "selected": false
              },
              {
                "value": "contact-2",
                "startIconUri": "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
                "text": "Contact 2",
                "bottomText": "Contact two description",
                "selected": false
              },
              {
                "value": "contact-3",
                "startIconUri": "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
                "text": "Contact 3",
                "bottomText": "Contact three description",
                "selected": false
              },
              {
                "value": "contact-4",
                "startIconUri": "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
                "text": "Contact 4",
                "bottomText": "Contact four description",
                "selected": false
              },
              {
                "value": "contact-5",
                "startIconUri": "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
                "text": "Contact 5",
                "bottomText": "Contact five description",
                "selected": false
              }
            ]
          }
        }
      ]
    }
  ]
}
all_widgets_are_required-Aktion in dateTimePicker festlegen

JSON

{
  "sections": [
    {
      "widgets": [
        {
          "textParagraph": {
            "text": "A datetime picker widget with both date and time:"
          }
        },
        {
          "divider": {}
        },
        {
          "dateTimePicker": {
            "name": "date_time_picker_date_and_time",
            "label": "meeting",
            "type": "DATE_AND_TIME"
          }
        },
        {
          "textParagraph": {
            "text": "A datetime picker widget with just date:"
          }
        },
        {
          "divider": {}
        },
        {
          "dateTimePicker": {
            "name": "date_time_picker_date_only",
            "label": "Choose a date",
            "type": "DATE_ONLY",
            "onChangeAction":{
              "all_widgets_are_required": true
            }
          }
        },
        {
          "textParagraph": {
            "text": "A datetime picker widget with just time:"
          }
        },
        {
          "divider": {}
        },
        {
          "dateTimePicker": {
            "name": "date_time_picker_time_only",
            "label": "Select a time",
            "type": "TIME_ONLY"
          }
        }
      ]
    }
  ]
}
all_widgets_are_required-Aktion im Drop-down-Menü festlegen

JSON

{
  "sections": [
    {
      "header": "Section Header",
      "collapsible": true,
      "uncollapsibleWidgetsCount": 1,
      "widgets": [
        {
          "selectionInput": {
            "name": "location",
            "label": "Select Color",
            "type": "DROPDOWN",
            "onChangeAction": {
              "all_widgets_are_required": true
            },
            "items": [
              {
                "text": "Red",
                "value": "red",
                "selected": false
              },
              {
                "text": "Green",
                "value": "green",
                "selected": false
              },
              {
                "text": "White",
                "value": "white",
                "selected": false
              },
              {
                "text": "Blue",
                "value": "blue",
                "selected": false
              },
              {
                "text": "Black",
                "value": "black",
                "selected": false
              }
            ]
          }
        }
      ]
    }
  ]
}

Validierung für ein Texteingabe-Widget festlegen

Im Validierungsfeld des Widgets textInput kann die Zeichenbeschränkung und der Eingabetyp für dieses Texteingabe-Widget angegeben werden.

Zeichenbeschränkung für ein Texteingabe-Widget festlegen

JSON

{
  "sections": [
    {
      "header": "Tell us about yourself",
      "collapsible": true,
      "uncollapsibleWidgetsCount": 2,
      "widgets": [
        {
          "textInput": {
            "name": "favoriteColor",
            "label": "Favorite color",
            "type": "SINGLE_LINE",
            "validation": {"character_limit":15},
            "onChangeAction":{
              "all_widgets_are_required": true
            }
          }
        }
      ]
    }
  ]
}
Eingabetyp für ein Texteingabe-Widget festlegen

JSON

{
  "sections": [
    {
      "header": "Validate text inputs by input types",
      "collapsible": true,
      "uncollapsibleWidgetsCount": 2,
      "widgets": [
        {
          "textInput": {
            "name": "mailing_address",
            "label": "Please enter a valid email address",
            "type": "SINGLE_LINE",
            "validation": {
              "input_type": "EMAIL"
            },
            "onChangeAction": {
              "all_widgets_are_required": true
            }
          }
        },
        {
          "textInput": {
            "name": "validate_integer",
            "label": "Please enter a number",
              "type": "SINGLE_LINE",
            "validation": {
              "input_type": "INTEGER"
            }
          }
        },
        {
          "textInput": {
            "name": "validate_float",
            "label": "Please enter a number with a decimal",
            "type": "SINGLE_LINE",
            "validation": {
              "input_type": "FLOAT"
            }
          }
        }
      ]
    }
  ]
}

Fehlerbehebung

Wenn eine Google Chat-App oder Karte einen Fehler zurückgibt, wird in der Chat-Oberfläche die Meldung „Ein Fehler ist aufgetreten“ angezeigt. oder „Ihre Anfrage kann nicht bearbeitet werden“. Manchmal wird in der Chat-Benutzeroberfläche keine Fehlermeldung angezeigt, aber die Chat-App oder ‑Karte liefert ein unerwartetes Ergebnis, z. B. wird eine Kartenmeldung nicht angezeigt.

Auch wenn in der Chat-Benutzeroberfläche keine Fehlermeldung angezeigt wird, sind beschreibende Fehlermeldungen und Protokolldaten verfügbar, die Ihnen helfen, Fehler zu beheben, wenn die Fehlerprotokollierung für Chat-Apps aktiviert ist. Informationen zum Ansehen, Debuggen und Beheben von Fehlern finden Sie unter Google Chat-Fehler beheben.

Chat-Apps, die keine Add-ons sind: Interaktive Karten und Dialogfelder entwerfen

Die folgende Dokumentation gilt für Chat-Apps, die keine Google Workspace-Add‑ons sind. Wenn Sie eine Google Chat-App migrieren möchten, die kein Add‑on ist, lesen Sie den Hilfeartikel Google Chat-App in ein Google Workspace-Add‑on umwandeln.

Der folgende Code zeigt ein Menü mit Mehrfachauswahl von Elementen aus einer externen Kontaktgruppe für den Nutzer in einer Chat-App, die kein Add-on ist. Im Menü wird standardmäßig ein Kontakt angezeigt. Die Funktion getContacts wird ausgeführt, um Elemente aus der externen Datenquelle abzurufen und einzufügen:

Node.js

node/selection-input/index.js
selectionInput: {
  name: "contacts",
  type: "MULTI_SELECT",
  label: "Selected contacts",
  multiSelectMaxSelectedItems: 3,
  multiSelectMinQueryLength: 1,
  externalDataSource: { function: "getContacts" },
  // Suggested items loaded by default.
  // The list is static here but it could be dynamic.
  items: [getContact("3")]
}

Python

python/selection-input/main.py
'selectionInput': {
  'name': "contacts",
  'type': "MULTI_SELECT",
  'label': "Selected contacts",
  'multiSelectMaxSelectedItems': 3,
  'multiSelectMinQueryLength': 1,
  'externalDataSource': { 'function': "getContacts" },
  # Suggested items loaded by default.
  # The list is static here but it could be dynamic.
  'items': [get_contact("3")]
}

Java

java/selection-input/src/main/java/com/google/chat/selectionInput/App.java
.setSelectionInput(new GoogleAppsCardV1SelectionInput()
  .setName("contacts")
  .setType("MULTI_SELECT")
  .setLabel("Selected contacts")
  .setMultiSelectMaxSelectedItems(3)
  .setMultiSelectMinQueryLength(1)
  .setExternalDataSource(new GoogleAppsCardV1Action().setFunction("getContacts"))
  .setItems(List.of(getContact("3")))))))))));

Apps Script

apps-script/selection-input/selection-input.gs
selectionInput: {
  name: "contacts",
  type: "MULTI_SELECT",
  label: "Selected contacts",
  multiSelectMaxSelectedItems: 3,
  multiSelectMinQueryLength: 1,
  externalDataSource: { function: "getContacts" },
  // Suggested items loaded by default.
  // The list is static here but it could be dynamic.
  items: [getContact("3")]
}

Wenn Sie Elemente in einer Chat-App, die kein Add-on ist, automatisch vervollständigen möchten, erstellen Sie eine Funktion, die die externe Datenquelle abfragt und Elemente zurückgibt, wenn ein Nutzer in das Mehrfachauswahlmenü eingibt. Die Funktion muss Folgendes tun:

  • Übergeben Sie ein Ereignisobjekt, das die Nutzerinteraktion mit dem Menü darstellt.
  • Prüfen Sie, ob der invokedFunction-Wert des Interaktionsereignisses mit der Funktion aus dem Feld externalDataSource übereinstimmt.
  • Wenn die Funktionen übereinstimmen, werden vorgeschlagene Elemente aus der externen Datenquelle zurückgegeben. Wenn Sie Elemente basierend auf der Eingabe des Nutzers vorschlagen möchten, rufen Sie den Wert für den Schlüssel autocomplete_widget_query ab. Dieser Wert entspricht dem, was der Nutzer in das Menü eingibt.

Mit dem folgenden Code werden Elemente aus einer externen Datenressource automatisch vervollständigt. Im vorherigen Beispiel schlägt die Chat-App, die kein Add-on ist, Elemente basierend darauf vor, wann die Funktion getContacts ausgelöst wird:

Node.js

node/selection-input/index.js
/**
 * Responds to a WIDGET_UPDATE event in Google Chat.
 *
 * @param {Object} event The event object from Chat API.
 * @return {Object} Response from the Chat app.
 */
function onWidgetUpdate(event) {
  if (event.common["invokedFunction"] === "getContacts") {
    const query = event.common.parameters["autocomplete_widget_query"];
    return { actionResponse: {
      type: "UPDATE_WIDGET",
      updatedWidget: { suggestions: { items: [
        // The list is static here but it could be dynamic.
        getContact("1"), getContact("2"), getContact("3"), getContact("4"), getContact("5")
      // Only return items based on the query from the user
      ].filter(e => !query || e.text.includes(query))}}
    }};
  }
}

/**
 * Generate a suggested contact given an ID.
 *
 * @param {String} id The ID of the contact to return.
 * @return {Object} The contact formatted as a suggested item for selectors.
 */
function getContact(id) {
  return {
    value: id,
    startIconUri: "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
    text: "Contact " + id
  };
}

Python

python/selection-input/main.py
def on_widget_update(event: dict) -> dict:
  """Responds to a WIDGET_UPDATE event in Google Chat."""
  if "getContacts" == event.get("common").get("invokedFunction"):
    query = event.get("common").get("parameters").get("autocomplete_widget_query")
    return { 'actionResponse': {
      'type': "UPDATE_WIDGET",
      'updatedWidget': { 'suggestions': { 'items': list(filter(lambda e: query is None or query in e["text"], [
        # The list is static here but it could be dynamic.
        get_contact("1"), get_contact("2"), get_contact("3"), get_contact("4"), get_contact("5")
      # Only return items based on the query from the user
      ]))}}
    }}


def get_contact(id: str) -> dict:
  """Generate a suggested contact given an ID."""
  return {
    'value': id,
    'startIconUri': "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
    'text': "Contact " + id
  }

Java

java/selection-input/src/main/java/com/google/chat/selectionInput/App.java
// Responds to a WIDGET_UPDATE event in Google Chat.
Message onWidgetUpdate(JsonNode event) {
  if ("getContacts".equals(event.at("/invokedFunction").asText())) {
    String query = event.at("/common/parameters/autocomplete_widget_query").asText();
    return new Message().setActionResponse(new ActionResponse()
      .setType("UPDATE_WIDGET")
      .setUpdatedWidget(new UpdatedWidget()
        .setSuggestions(new SelectionItems().setItems(List.of(
          // The list is static here but it could be dynamic.
          getContact("1"), getContact("2"), getContact("3"), getContact("4"), getContact("5")
        // Only return items based on the query from the user
        ).stream().filter(e -> query == null || e.getText().indexOf(query) > -1).toList()))));
  }
  return null;
}

// Generate a suggested contact given an ID.
GoogleAppsCardV1SelectionItem getContact(String id) {
  return new GoogleAppsCardV1SelectionItem()
    .setValue(id)
    .setStartIconUri("https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png")
    .setText("Contact " + id);
}

Apps Script

apps-script/selection-input/selection-input.gs
/**
 * Responds to a WIDGET_UPDATE event in Google Chat.
 *
 * @param {Object} event The event object from Chat API.
 * @return {Object} Response from the Chat app.
 */
function onWidgetUpdate(event) {
  if (event.common["invokedFunction"] === "getContacts") {
    const query = event.common.parameters["autocomplete_widget_query"];
    return { actionResponse: {
      type: "UPDATE_WIDGET",
      updatedWidget: { suggestions: { items: [
        // The list is static here but it could be dynamic.
        getContact("1"), getContact("2"), getContact("3"), getContact("4"), getContact("5")
      // Only return items based on the query from the user
      ].filter(e => !query || e.text.includes(query))}}
    }};
  }
}

/**
 * Generate a suggested contact given an ID.
 *
 * @param {String} id The ID of the contact to return.
 * @return {Object} The contact formatted as a suggested item for selectors.
 */
function getContact(id) {
  return {
    value: id,
    startIconUri: "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
    text: "Contact " + id
  };
}