Dodawanie interaktywnych elementów interfejsu do kart

Na tej stronie wyjaśniamy, jak dodawać widżety i elementy interfejsu do kart, aby użytkownicy mogli wchodzić w interakcje z aplikacją Google Chat, np. klikać przyciski lub przesyłać informacje.

Aplikacje do Google Chat mogą używać tych interfejsów Google Chat do tworzenia kart interaktywnych:

  • Wiadomości zawierające co najmniej 1 kartę.
  • Strony główne, czyli karty wyświetlane na karcie Strona główna w czatach z aplikacją Google Chat.
  • okna, czyli karty, które otwierają się w nowym oknie z wiadomości i stron głównych;

Gdy użytkownicy wchodzą w interakcję z kartami, aplikacje do Google Chat mogą używać otrzymanych danych do przetwarzania i odpowiedniego reagowania. Szczegółowe informacje znajdziesz w artykule Zbieranie i przetwarzanie informacji od użytkowników Google Chat.


Za pomocą Kreatora kart możesz projektować i wyświetlać podgląd wiadomości oraz interfejsów aplikacji do Google Chat:

Otwieranie Kreatora kart

Wymagania wstępne

Aplikacja Google Chat skonfigurowana do odbierania interakcji użytkowników i odpowiadania na nie. Aby utworzyć interaktywną aplikację do Google Chat, wykonaj czynności opisane w jednym z tych krótkich przewodników, w zależności od architektury aplikacji, której chcesz użyć:

Dodawanie przycisku

Widżet ButtonList wyświetla zestaw przycisków. Przyciski mogą wyświetlać tekst, ikonę lub tekst i ikonę. Każdy element Button obsługuje działanie OnClick, które jest wykonywane, gdy użytkownik kliknie przycisk. Na przykład:

  • Otwórz hiperlink za pomocą OpenLink, aby przekazać użytkownikom dodatkowe informacje.
  • Uruchom action, który uruchamia funkcję niestandardową, np. wywołuje interfejs API.

W celu ułatwienia dostępu przyciski obsługują tekst alternatywny.

Dodawanie przycisku, który uruchamia funkcję niestandardową

Poniżej znajduje się karta składająca się z widżetu ButtonList z 2 przyciskami. Jeden przycisk otwiera dokumentację dla deweloperów Google Chat w nowej karcie. Drugi przycisk uruchamia funkcję niestandardową o nazwie goToView() i przekazuje parametr viewType="BIRD EYE VIEW".

Dodawanie przycisku w stylu Material Design

Poniżej znajdziesz zestaw przycisków w różnych stylach Material Design.

Aby zastosować styl Material Design, nie dodawaj atrybutu „color”.

Dodaj przycisk z kolorem niestandardowym i wyłączony przycisk

Możesz uniemożliwić użytkownikom klikanie przycisku, ustawiając "disabled": "true".

Poniżej znajduje się karta składająca się z widżetu ButtonList z 2 przyciskami. Jeden przycisk używa pola Color, aby dostosować kolor tła przycisku. Drugi przycisk jest dezaktywowany za pomocą pola Disabled, co uniemożliwia użytkownikowi kliknięcie przycisku i wykonanie funkcji.

Dodawanie przycisku z ikoną

Poniżej znajduje się karta składająca się z widżetu ButtonList z 2 widżetami ikon Button. Jeden przycisk używa pola knownIcon do wyświetlania wbudowanej ikony e-maila w Google Chat. Drugi przycisk używa pola iconUrl do wyświetlania widżetu ikony niestandardowej.

Dodawanie przycisku z ikoną i tekstem

Poniżej znajduje się karta z widżetem ButtonList, który prosi użytkownika o wysłanie e-maila. Na pierwszym przycisku wyświetla się ikona e-maila, a na drugim – tekst. Użytkownik może kliknąć ikonę lub przycisk tekstowy, aby uruchomić funkcję sendEmail.

Dostosowywanie przycisku sekcji zwijanej

Dostosuj przycisk sterujący, który zwija i rozwija sekcje na karcie. Wybierz spośród różnych ikon lub obrazów, aby wizualnie przedstawić zawartość sekcji, co ułatwi użytkownikom zrozumienie informacji i interakcję z nimi.

Dodawanie rozszerzonego menu

Overflow menu może być używany na kartach Google Chat, aby oferować dodatkowe opcje i działania. Dzięki temu możesz uwzględnić więcej opcji bez zaśmiecania interfejsu karty, co zapewnia przejrzysty i uporządkowany wygląd.

Dodawanie listy elementów

Widżet ChipList to wszechstronny i atrakcyjny wizualnie sposób wyświetlania informacji. Używaj list elementów, aby przedstawiać tagi, kategorie lub inne istotne dane, ułatwiając użytkownikom poruszanie się po treściach i interakcję z nimi.

Zbieranie informacji od użytkowników

W tej sekcji dowiesz się, jak dodawać widżety, które zbierają informacje, takie jak tekst lub wybory.

Aby dowiedzieć się, jak przetwarzać dane wprowadzane przez użytkowników, przeczytaj artykuł o zbieraniu i przetwarzaniu informacji od użytkowników Google Chat.

Zbieranie tekstu

Widżet TextInput udostępnia pole, w którym użytkownicy mogą wpisywać tekst. Widżet obsługuje sugestie, które pomagają użytkownikom wprowadzać jednolite dane, oraz działania po zmianie, czyli Actions, które są uruchamiane, gdy nastąpi zmiana w polu do wprowadzania danych, np. gdy użytkownik doda lub usunie tekst.

Gdy chcesz zbierać od użytkowników abstrakcyjne lub nieznane dane, użyj widżetu TextInput. Aby zbierać od użytkowników określone dane, użyj widżetu SelectionInput.

Poniżej znajduje się karta zawierająca widżet TextInput:

Zbieranie dat lub godzin

Widżet DateTimePicker umożliwia użytkownikom wpisywanie daty, godziny lub daty i godziny. Użytkownicy mogą też wybrać datę i godzinę za pomocą selektora. Jeśli użytkownicy wpiszą nieprawidłową datę lub godzinę, selektor wyświetli błąd z prośbą o wpisanie prawidłowych informacji.

Poniżej znajduje się karta składająca się z 3 różnych typów widżetów DateTimePicker:

Zezwalanie użytkownikom na wybieranie elementów

Widżet SelectionInput udostępnia zestaw elementów do wyboru, takich jak pola wyboru, przyciski opcji, przełączniki lub menu. Możesz używać tego widżetu do zbierania od użytkowników zdefiniowanych i ujednoliconych danych. Aby zbierać od użytkowników niezdefiniowane dane, użyj widżetu TextInput.

Widżet SelectionInput obsługuje sugestie, które pomagają użytkownikom wprowadzać jednolite dane, oraz działania po zmianie, czyli Actions, które są uruchamiane, gdy nastąpi zmiana w polu do wprowadzania danych, np. gdy użytkownik zaznaczy lub odznaczy element.

Aplikacje do obsługi czatu mogą odbierać i przetwarzać wartości wybranych elementów. Szczegółowe informacje o pracy z danymi wejściowymi formularza znajdziesz w artykule Przetwarzanie informacji wprowadzonych przez użytkowników.

Ta sekcja zawiera przykłady kart, które używają widżetu SelectionInput. W przykładach użyto różnych typów danych wejściowych sekcji:

Dodawanie pola wyboru

Poniżej znajduje się karta, która prosi użytkownika o określenie, czy kontakt jest służbowy, osobisty czy oba, z widżetem SelectionInput, który używa pól wyboru:

Dodawanie opcji

Poniżej znajduje się karta, która prosi użytkownika o określenie, czy kontakt jest służbowy czy osobisty, za pomocą widżetu SelectionInput, który używa przycisków opcji:

Dodawanie przełącznika

Poniżej znajduje się karta, która prosi użytkownika o określenie, czy kontakt jest służbowy, osobisty czy oba, za pomocą widżetu SelectionInput, który używa przełączników:

Poniżej znajduje się karta, która prosi użytkownika o określenie, czy kontakt jest służbowy czy prywatny, za pomocą widżetu SelectionInput, który korzysta z menu:

dynamicznie wypełniać menu,

Dostępne w przypadku aplikacji Google Chat.

Możesz dynamicznie wypełniać elementy menu z rozwijaną listą, korzystając ze źródeł danych w Google Workspace lub z zewnętrznego źródła danych. Aby używać dynamicznych źródeł danych, określ pole dataSourceConfigs, które jest tablicą obiektów DataSourceConfig. Każdy element DataSourceConfig może zawierać element platformDataSource lub remoteDataSource. Obecnie obsługiwany jest tylko 1 DataSourceConfig.

Wypełnianie elementów z Google Workspace

Aby wypełnić elementy ze źródeł danych Google Workspace, takich jak użytkownicy Google Workspace, określ pole platformDataSource w DataSourceConfig. W przeciwieństwie do używania statycznego items pomijasz obiekty SelectionItem, ponieważ te elementy wyboru są dynamicznie pobierane z Google Workspace.

Poniższy kod pokazuje menu, które wypełnia użytkowników Google Workspace:

JSON

{
  "sections": [
    {
      "header": "Section Header",
      "widgets": [
        {
          "selectionInput": {
            "name": "contacts",
            "type": "DROPDOWN",
            "label": "Select contact from organization",
            "dataSourceConfigs": [
              {
                "platformDataSource": {
                  "commonDataSource": "USER"
                },
                "minCharactersTrigger": 1
              }
            ]
          }
        }
      ]
    }
  ]
}
Wypełnianie elementów z zewnętrznego źródła danych

Aby wypełnić elementy z zewnętrznego źródła danych, takiego jak system zarządzania relacjami z klientami (CRM), użyj pola remoteDataSource w DataSourceConfig, aby określić funkcję, która zwraca elementy ze źródła danych.

Poniższy kod pokazuje menu, które wypełnia elementy z zewnętrznego zestawu kontaktów przez uruchomienie funkcji getCrmLeads:

JSON

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

Aby zmniejszyć liczbę żądań wysyłanych do dynamicznego źródła danych, możesz uwzględnić sugerowane elementy, które pojawiają się w menu, zanim użytkownicy zaczną pisać. Możesz też skonfigurować menu, aby automatycznie uzupełniało elementy na podstawie tego, co wpisują użytkownicy, ustawiając minCharactersTrigger w DataSourceConfig. Gdy użytkownik wpisze co najmniej liczbę znaków określoną w minCharactersTrigger, zostanie wywołana funkcja określona w remoteDataSource. Obiekt zdarzenia przekazywany do funkcji zawiera dane wejściowe użytkownika w kluczu autocomplete_widget_query.

Dodawanie menu wielokrotnego wyboru

Poniżej znajduje się karta, która prosi użytkownika o wybranie kontaktów z menu wielokrotnego wyboru:

Elementy menu wielokrotnego wyboru możesz wypełniać danymi z tych źródeł danych w Google Workspace:

  • Użytkownicy Google Workspace: możesz dodawać tylko użytkowników z tej samej organizacji Google Workspace.
  • Pokoje czatu: użytkownik wprowadzający elementy w menu wielokrotnego wyboru może wyświetlać i wybierać tylko te pokoje, do których należy w swojej organizacji Google Workspace.

Aby używać źródeł danych Google Workspace, określ pole platformDataSource. W przeciwieństwie do innych typów danych wejściowych wyboru pomijasz obiekty SelectionItem, ponieważ te elementy wyboru są pobierane dynamicznie z Google Workspace.

Poniższy kod przedstawia menu wielokrotnego wyboru użytkowników Google Workspace. Aby wypełnić listę użytkowników, pole wyboru ustawia parametr commonDataSource na wartość USER:

JSON

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

Poniższy kod pokazuje menu wielokrotnego wyboru pokoi czatu. Aby wypełnić pokoje, dane wejściowe wyboru określają pole hostAppDataSource. Menu wielokrotnego wyboru ustawia też właściwość defaultToCurrentSpace na true, co sprawia, że bieżący pokój jest domyślnym wyborem w menu:

JSON

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

Menu wielokrotnego wyboru mogą też wypełniać elementy z zewnętrznego źródła danych. Możesz na przykład użyć menu wielokrotnego wyboru, aby pomóc użytkownikowi wybrać pozycję z listy potencjalnych sprzedaży z systemu zarządzania relacjami z klientami (CRM).

Aby użyć zewnętrznego źródła danych, użyj pola externalDataSource, aby określić funkcję, która zwraca elementy ze źródła danych.

Aby zmniejszyć liczbę żądań wysyłanych do zewnętrznego źródła danych, możesz uwzględnić sugerowane elementy, które pojawiają się w menu wielokrotnego wyboru, zanim użytkownicy zaczną wpisywać tekst w menu. Możesz na przykład wyświetlić użytkownikowi ostatnio wyszukiwane kontakty. Aby wypełnić sugerowane elementy z zewnętrznego źródła danych, określ obiekty SelectionItem.

Poniższy przykładowy kod pokazuje menu wielokrotnego wyboru, które wysyła zapytania i wypełnia elementy z zewnętrznego źródła danych:

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")]
}

Zastąp FUNCTION_URL punktem końcowym HTTP, który wysyła zapytania do zewnętrznego źródła danych.

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")]
}

Zastąp FUNCTION_URL punktem końcowym HTTP, który wysyła zapytania do zewnętrznego źródła danych.

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

Zastąp FUNCTION_URL punktem końcowym HTTP, który wysyła zapytania do zewnętrznego źródła danych.

Google Apps Script

Ten przykład wysyła wiadomość z kartą, zwracając kod JSON karty. Możesz też użyć usługi kart Apps Script.

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")]
}

Wypełnianie sugerowanych elementów z dynamicznego źródła danych

W przypadku zewnętrznych źródeł danych możesz też autouzupełniać i sugerować elementy, które użytkownicy zaczynają wpisywać w menu wielokrotnego wyboru lub menu. Jeśli na przykład użytkownik zacznie wpisywać Atl w menu, które zawiera miasta w Stanach Zjednoczonych, aplikacja do Google Chat może automatycznie zasugerować Atlanta, zanim użytkownik skończy pisać. Możesz zaproponować maksymalnie 100 elementów.

Aby zwracać sugerowane elementy, funkcja wysyłająca zapytanie do zewnętrznego źródła danych musi:

  1. Obsługiwać obiekt zdarzenia, który aplikacja do obsługi czatu otrzymuje, gdy użytkownicy wpisują tekst w menu.
  2. Z obiektu zdarzenia pobierz wartość wpisaną przez użytkownika, która jest reprezentowana w polu event.commonEventObject.parameters["autocomplete_widget_query"].
  3. Wyślij zapytanie do źródła danych, używając wartości wprowadzonej przez użytkownika, aby uzyskać co najmniej 1 SelectionItems do zasugerowania użytkownikowi.
  4. Zwróć sugerowane elementy, zwracając działanie RenderActions z obiektem modifyCard.

Poniższy przykładowy kod pokazuje, jak aplikacja Google Chat dynamicznie sugeruje elementy w menu wielokrotnego wyboru na karcie. Gdy użytkownik wpisze coś w menu, funkcja lub punkt końcowy podane w polu externalDataSource widżetu wysyłają zapytanie do zewnętrznego źródła danych i sugerują elementy, które użytkownik może wybrać:

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

Zastąp FUNCTION_URL punktem końcowym HTTP, który wysyła zapytania do zewnętrznego źródła danych.

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
  }

Zastąp FUNCTION_URL punktem końcowym HTTP, który wysyła zapytania do zewnętrznego źródła danych.

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

Zastąp FUNCTION_URL punktem końcowym HTTP, który wysyła zapytania do zewnętrznego źródła danych.

Google Apps Script

Ten przykład wysyła wiadomość z kartą, zwracając kod JSON karty. Możesz też użyć usługi kart Apps Script.

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

Sprawdzanie danych wprowadzonych na kartach

Na tej stronie dowiesz się, jak sprawdzać poprawność danych wprowadzonych w action i widżetach karty. Możesz na przykład sprawdzić, czy pole do wprowadzania danych zawiera tekst wpisany przez użytkownika lub czy zawiera określoną liczbę znaków.

Ustawianie wymaganych widżetów dla działań

W ramach action karty dodaj nazwy widżetów, których wymaga działanie, do listy requiredWidgets.

Jeśli którykolwiek z wymienionych tu widżetów nie ma wartości, gdy to działanie jest wywoływane, przesyłanie działania formularza jest anulowane.

Gdy dla działania ustawiona jest wartość "allWidgetsAreRequired": true, wszystkie widżety na karcie są wymagane przez to działanie.

Ustawianie działania allWidgetsAreRequired w trybie wielokrotnego wyboru

JSON

{
  "sections": [
    {
      "header": "Select contacts",
      "widgets": [
        {
          "selectionInput": {
            "type": "MULTI_SELECT",
            "label": "Selected contacts",
            "name": "contacts",
            "multiSelectMaxSelectedItems": 3,
            "multiSelectMinQueryLength": 1,
            "onChangeAction": {
              "allWidgetsAreRequired": 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
              }
            ]
          }
        }
      ]
    }
  ]
}
Ustaw działanie allWidgetsAreRequired w selektorze daty i godziny

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":{
              "allWidgetsAreRequired": 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"
          }
        }
      ]
    }
  ]
}
Ustaw działanie allWidgetsAreRequired w menu

JSON

{
  "sections": [
    {
      "header": "Section Header",
      "collapsible": true,
      "uncollapsibleWidgetsCount": 1,
      "widgets": [
        {
          "selectionInput": {
            "name": "location",
            "label": "Select Color",
            "type": "DROPDOWN",
            "onChangeAction": {
              "allWidgetsAreRequired": 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
              }
            ]
          }
        }
      ]
    }
  ]
}

Ustawianie weryfikacji widżetu do wprowadzania tekstu

W polu weryfikacji widżetu textInput można określić limit znaków i typ danych wejściowych dla tego widżetu do wprowadzania tekstu.

Ustawianie limitu znaków w widżecie do wprowadzania tekstu

JSON

{
  "sections": [
    {
      "header": "Tell us about yourself",
      "collapsible": true,
      "uncollapsibleWidgetsCount": 2,
      "widgets": [
        {
          "textInput": {
            "name": "favoriteColor",
            "label": "Favorite color",
            "type": "SINGLE_LINE",
            "validation": {"characterLimit": 15},
            "onChangeAction":{
              "allWidgetsAreRequired": true
            }
          }
        }
      ]
    }
  ]
}
Ustawianie typu danych wejściowych dla widżetu do wprowadzania tekstu

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": {
              "inputType": "EMAIL"
            },
            "onChangeAction": {
              "allWidgetsAreRequired": true
            }
          }
        },
        {
          "textInput": {
            "name": "validate_integer",
            "label": "Please enter a number",
              "type": "SINGLE_LINE",
            "validation": {
              "inputType": "INTEGER"
            }
          }
        },
        {
          "textInput": {
            "name": "validate_float",
            "label": "Please enter a number with a decimal",
            "type": "SINGLE_LINE",
            "validation": {
              "inputType": "FLOAT"
            }
          }
        }
      ]
    }
  ]
}

Rozwiązywanie problemów

Gdy aplikacja Google Chat lub karta zwraca błąd, interfejs Google Chat wyświetla komunikat „Coś poszło nie tak”. lub „Nie udało się przetworzyć żądania”. Czasami interfejs Google Chat nie wyświetla żadnego komunikatu o błędzie, ale aplikacja lub karta Google Chat generuje nieoczekiwany wynik, np. wiadomość na karcie może się nie pojawić.

Chociaż komunikat o błędzie może nie wyświetlać się w interfejsie Google Chat, opisowe komunikaty o błędach i dane dziennika są dostępne, aby pomóc Ci naprawić błędy, gdy włączone jest rejestrowanie błędów w aplikacjach Google Chat. Pomoc dotyczącą wyświetlania, debugowania i naprawiania błędów znajdziesz w artykule Rozwiązywanie problemów z Google Chat.

Aplikacje do Google Chat, które nie są dodatkami: projektowanie interaktywnych kart i okien dialogowych

Poniższa dokumentacja dotyczy aplikacji do Google Chat, które nie są dodatkami do Google Workspace. Aby dowiedzieć się, jak przenieść aplikację do Google Chat, która nie jest dodatkiem, przeczytaj artykuł Przekształcanie aplikacji do Google Chat w dodatek do Google Workspace.

Poniższy kod pokazuje menu wielokrotnego wyboru elementów z zewnętrznego zestawu kontaktów użytkownika w aplikacji Google Chat, która nie jest dodatkiem. Menu domyślnie wyświetla 1 kontakt i uruchamia funkcję getContacts, aby pobrać i wypełnić elementy z zewnętrznego źródła danych:

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

Google 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")]
}

Aby automatycznie uzupełniać elementy w aplikacji do Google Chat, która nie jest dodatkiem, utwórz funkcję, która wysyła zapytania do zewnętrznego źródła danych i zwraca elementy, gdy użytkownik wpisuje tekst w menu wielokrotnego wyboru. Funkcja musi wykonywać te czynności:

  • Przekaż obiekt zdarzenia, który reprezentuje interakcję użytkownika z menu.
  • Sprawdź, czy wartość invokedFunction zdarzenia interakcji odpowiada funkcji z pola externalDataSource.
  • Gdy funkcje pasują do siebie, zwróć sugerowane elementy z zewnętrznego źródła danych. Aby sugerować elementy na podstawie tego, co wpisuje użytkownik, pobierz wartość klucza autocomplete_widget_query. Ta wartość reprezentuje to, co użytkownik wpisuje w menu.

Poniższy kod automatycznie uzupełnia elementy z zewnętrznego zasobu danych. W poprzednim przykładzie aplikacja do Google Chat, która nie jest dodatkiem, sugeruje elementy na podstawie momentu wywołania funkcji getContacts:

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

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