เพิ่มองค์ประกอบ UI แบบอินเทอร์แอกทีฟลงในการ์ด

หน้านี้อธิบายวิธีเพิ่มวิดเจ็ตและองค์ประกอบ UI ลงในการ์ดเพื่อให้ผู้ใช้โต้ตอบกับแอป Google Chat ได้ เช่น โดยการคลิกปุ่มหรือส่งข้อมูล

แอปใน Chat สามารถใช้อินเทอร์เฟซ Chat ต่อไปนี้เพื่อสร้างการ์ดแบบอินเทอร์แอกทีฟได้

  • ข้อความที่มีการ์ดอย่างน้อย 1 รายการ
  • หน้าแรก ซึ่งเป็นการ์ดที่ปรากฏจากแท็บหน้าแรกในข้อความส่วนตัวที่มีแอปใน Chat
  • กล่องโต้ตอบ ซึ่งเป็นการ์ดที่เปิดในหน้าต่างใหม่จากข้อความและหน้าแรก

เมื่อผู้ใช้โต้ตอบกับการ์ด แอปใน Chat จะใช้ข้อมูลที่ได้รับเพื่อประมวลผลและตอบกลับตามความเหมาะสมได้ โปรดดูรายละเอียดที่หัวข้อรวบรวมและประมวลผลข้อมูลจากผู้ใช้ Google Chat


ใช้เครื่องมือสร้างการ์ดเพื่อออกแบบและดูตัวอย่างการรับส่งข้อความและอินเทอร์เฟซผู้ใช้สำหรับแอปใน Chat ดังนี้

เปิดเครื่องมือสร้างการ์ด

ข้อกำหนดเบื้องต้น

แอป Google Chat ที่กำหนดค่าให้รับและตอบสนองต่อการโต้ตอบของผู้ใช้ หากต้องการสร้างแอป Chat แบบอินเทอร์แอกทีฟ ให้ทำตามคู่มือเริ่มใช้งานฉบับย่อข้อใดข้อหนึ่งต่อไปนี้โดยอิงตามสถาปัตยกรรมแอปที่คุณต้องการใช้

เพิ่มปุ่ม

วิดเจ็ต ButtonList จะแสดงชุดปุ่ม ปุ่มสามารถแสดงข้อความ ไอคอน หรือทั้งข้อความและไอคอน Button แต่ละรายการรองรับการดำเนินการ OnClick ที่เกิดขึ้นเมื่อผู้ใช้คลิกปุ่ม เช่น

  • เปิดไฮเปอร์ลิงก์ด้วย OpenLink เพื่อให้ข้อมูลเพิ่มเติมแก่ผู้ใช้
  • เรียกใช้ action ที่เรียกใช้ฟังก์ชันที่กำหนดเอง เช่น การเรียก API

ปุ่มรองรับข้อความสำรองเพื่อการช่วยเหลือพิเศษ

เพิ่มปุ่มที่เรียกใช้ฟังก์ชันที่กำหนดเอง

ต่อไปนี้คือการ์ดที่ประกอบด้วยวิดเจ็ต ButtonList ที่มีปุ่ม 2 ปุ่ม ปุ่มหนึ่งจะเปิดเอกสารประกอบสำหรับนักพัฒนาซอฟต์แวร์ Google Chat ในแท็บใหม่ ส่วนอีกปุ่มจะเรียกใช้ฟังก์ชันที่กำหนดเองชื่อ goToView() และส่งพารามิเตอร์ viewType="BIRD EYE VIEW"

เพิ่มปุ่มที่มีสไตล์ Material Design

ต่อไปนี้แสดงชุดปุ่มในรูปแบบปุ่ม Material Design ที่แตกต่างกัน

หากต้องการใช้รูปแบบ Material Design อย่าใส่แอตทริบิวต์ "color"

เพิ่มปุ่มที่มีสีแบบกำหนดเองและปุ่มที่ปิดใช้งาน

คุณป้องกันไม่ให้ผู้ใช้คลิกปุ่มได้โดยตั้งค่า "disabled": "true"

ตัวอย่างต่อไปนี้แสดงการ์ดที่ประกอบด้วยวิดเจ็ต ButtonList ที่มีปุ่ม 2 ปุ่ม ปุ่มหนึ่งใช้ช่อง Color เพื่อปรับแต่งสีพื้นหลังของปุ่ม ปุ่มอื่นจะปิดใช้งานด้วยช่อง Disabled ซึ่งจะป้องกันไม่ให้ผู้ใช้คลิกปุ่มและเรียกใช้ฟังก์ชัน

เพิ่มปุ่มที่มีไอคอน

ตัวอย่างต่อไปนี้แสดงการ์ดที่ประกอบด้วยวิดเจ็ต ButtonList ที่มีวิดเจ็ตไอคอน Button 2 รายการ ปุ่มหนึ่งใช้ช่อง knownIcon เพื่อแสดงไอคอนอีเมลในตัวของ Google Chat ปุ่มอีกปุ่มหนึ่งใช้ฟิลด์ iconUrl เพื่อแสดงวิดเจ็ตไอคอนที่กำหนดเอง

เพิ่มปุ่มที่มีไอคอนและข้อความ

ตัวอย่างต่อไปนี้แสดงการ์ดที่ประกอบด้วยวิดเจ็ต ButtonList ซึ่งแจ้งให้ผู้ใช้ส่งอีเมล ปุ่มแรกจะแสดงไอคอนอีเมลและปุ่มที่ 2 จะแสดงข้อความ ผู้ใช้สามารถคลิกปุ่มไอคอนหรือปุ่มข้อความเพื่อเรียกใช้ฟังก์ชันsendEmailได้

ปรับแต่งปุ่มสำหรับส่วนที่ยุบได้

ปรับแต่งปุ่มควบคุมที่ยุบและขยายส่วนต่างๆ ภายในบัตร เลือกจากไอคอนหรือรูปภาพที่หลากหลายเพื่อแสดงเนื้อหาของส่วนนั้นๆ ในรูปแบบภาพ ซึ่งจะช่วยให้ผู้ใช้เข้าใจและโต้ตอบกับข้อมูลได้ง่ายขึ้น

เพิ่มเมนูรายการเพิ่มเติม

Overflow menu สามารถใช้ในการ์ดแชทเพื่อเสนอตัวเลือกและการดำเนินการเพิ่มเติม ซึ่งช่วยให้คุณใส่ตัวเลือกเพิ่มเติมได้โดยไม่ทำให้หน้าจอของการ์ดดูรก และยังช่วยให้การออกแบบดูสะอาดตาและเป็นระเบียบ

เพิ่มรายการชิป

วิดเจ็ต ChipList เป็นวิธีที่อเนกประสงค์และดึงดูดสายตาในการแสดงข้อมูล ใช้รายการชิปเพื่อแสดงแท็ก หมวดหมู่ หรือข้อมูลอื่นๆ ที่เกี่ยวข้อง ซึ่งจะช่วยให้ผู้ใช้ไปยังส่วนต่างๆ และโต้ตอบกับเนื้อหาได้ง่ายขึ้น

รวบรวมข้อมูลจากผู้ใช้

ส่วนนี้จะอธิบายวิธีเพิ่มวิดเจ็ตที่รวบรวมข้อมูล เช่น ข้อความหรือการเลือก

ดูวิธีประมวลผลสิ่งที่ผู้ใช้ป้อนได้ที่หัวข้อรวบรวมและประมวลผลข้อมูลจากผู้ใช้ Google Chat

รวบรวมข้อความ

วิดเจ็ต TextInput มีช่องที่ผู้ใช้สามารถป้อนข้อความได้ วิดเจ็ตนี้รองรับคำแนะนำซึ่งช่วยให้ผู้ใช้ป้อนข้อมูลที่สอดคล้องกัน และการดำเนินการเมื่อมีการเปลี่ยนแปลง ซึ่งก็คือ Actions ที่จะทำงานเมื่อมีการเปลี่ยนแปลงในช่องป้อนข้อความ เช่น ผู้ใช้เพิ่มหรือลบข้อความ

เมื่อต้องการรวบรวมข้อมูลนามธรรมหรือไม่รู้จักจากผู้ใช้ ให้ใช้วิดเจ็ต TextInput นี้ หากต้องการรวบรวมข้อมูลที่กำหนดจากผู้ใช้ ให้ใช้วิดเจ็ต SelectionInput แทน

ต่อไปนี้คือการ์ดที่ประกอบด้วยวิดเจ็ต TextInput

รวบรวมวันที่หรือเวลา

วิดเจ็ต DateTimePicker ช่วยให้ผู้ใช้ป้อนวันที่ เวลา หรือทั้งวันที่และเวลาได้ หรือผู้ใช้จะใช้เครื่องมือเลือกเพื่อเลือกวันที่และเวลาก็ได้ หากผู้ใช้ป้อนวันที่หรือเวลาที่ไม่ถูกต้อง เครื่องมือเลือกจะแสดงข้อผิดพลาดที่แจ้งให้ผู้ใช้ป้อนข้อมูลให้ถูกต้อง

ตัวอย่างต่อไปนี้แสดงการ์ดที่ประกอบด้วยวิดเจ็ต DateTimePicker 3 ประเภทที่แตกต่างกัน

อนุญาตให้ผู้ใช้เลือกรายการ

วิดเจ็ต SelectionInput มีชุดรายการที่เลือกได้ เช่น ช่องทำเครื่องหมาย ปุ่มตัวเลือก สวิตช์ หรือเมนูแบบเลื่อนลง คุณสามารถใช้วิดเจ็ตนี้เพื่อรวบรวมข้อมูลที่กำหนดและเป็นมาตรฐานจากผู้ใช้ หากต้องการรวบรวมข้อมูลที่ไม่ได้กำหนดจากผู้ใช้ ให้ใช้วิดเจ็ต TextInput แทน

วิดเจ็ต SelectionInput รองรับคำแนะนำ ซึ่งช่วยให้ผู้ใช้ป้อนข้อมูลที่สอดคล้องกัน และการดำเนินการเมื่อมีการเปลี่ยนแปลง ซึ่งเป็นActionsที่ทำงานเมื่อมีการเปลี่ยนแปลงในช่องป้อนข้อมูลการเลือก เช่น ผู้ใช้เลือกหรือยกเลิกการเลือกรายการ

แอปใน Chat จะรับและประมวลผลค่าของรายการที่เลือกได้ ดูรายละเอียดเกี่ยวกับการทำงานกับอินพุตของแบบฟอร์มได้ที่หัวข้อประมวลผลข้อมูลที่ผู้ใช้ป้อน

ส่วนนี้แสดงตัวอย่างการ์ดที่ใช้วิดเจ็ต SelectionInput ตัวอย่างจะใช้อินพุตส่วนประเภทต่างๆ ดังนี้

เพิ่มช่องทำเครื่องหมาย

ตัวอย่างต่อไปนี้แสดงการ์ดที่ขอให้ผู้ใช้ระบุว่ารายชื่อติดต่อเป็นรายชื่อติดต่อทางวิชาชีพ ส่วนตัว หรือทั้ง 2 อย่าง โดยมีวิดเจ็ต SelectionInput ที่ใช้ช่องทำเครื่องหมาย

เพิ่มปุ่มตัวเลือก

ตัวอย่างต่อไปนี้แสดงการ์ดที่ขอให้ผู้ใช้ระบุว่ารายชื่อติดต่อเป็นแบบมืออาชีพหรือส่วนตัวด้วยวิดเจ็ต SelectionInput ที่ใช้ปุ่มตัวเลือก

เพิ่มสวิตช์

ตัวอย่างต่อไปนี้แสดงการ์ดที่ขอให้ผู้ใช้ระบุว่ารายชื่อติดต่อเป็นแบบมืออาชีพ ส่วนตัว หรือทั้ง 2 อย่างด้วยวิดเจ็ต SelectionInput ที่ใช้สวิตช์

ตัวอย่างต่อไปนี้แสดงการ์ดที่ขอให้ผู้ใช้ระบุว่ารายชื่อติดต่อเป็นรายชื่อติดต่อทางธุรกิจหรือส่วนตัวด้วยวิดเจ็ต SelectionInput ที่ใช้เมนูแบบเลื่อนลง

สร้างเมนูแบบเลื่อนลงแบบไดนามิก

ใช้ได้กับแอป Google Chat

คุณสามารถป้อนข้อมูลรายการสำหรับเมนูแบบเลื่อนลงแบบไดนามิกจากแหล่งข้อมูลใน Google Workspace หรือจากแหล่งข้อมูลภายนอกได้ หากต้องการใช้แหล่งข้อมูลแบบไดนามิก ให้ระบุช่อง dataSourceConfigs ซึ่งเป็นอาร์เรย์ของออบเจ็กต์ DataSourceConfig DataSourceConfig แต่ละรายการอาจมี platformDataSource หรือ remoteDataSource ก็ได้ ปัจจุบันรองรับ DataSourceConfig เพียงรายการเดียวเท่านั้น

ป้อนข้อมูลจาก Google Workspace

หากต้องการสร้างรายการจากแหล่งข้อมูล Google Workspace เช่น ผู้ใช้ Google Workspace ให้ระบุช่อง platformDataSource ภายใน DataSourceConfig คุณจะละเว้นออบเจ็กต์ SelectionItem ซึ่งต่างจากการใช้ items แบบคงที่ เนื่องจากรายการที่เลือกเหล่านี้มาจาก Google Workspace แบบไดนามิก

โค้ดต่อไปนี้แสดงเมนูแบบเลื่อนลงที่สร้างผู้ใช้ Google Workspace

JSON

{
  "sections": [
    {
      "header": "Section Header",
      "widgets": [
        {
          "selectionInput": {
            "name": "contacts",
            "type": "DROPDOWN",
            "label": "Select contact from organization",
            "dataSourceConfigs": [
              {
                "platformDataSource": {
                  "commonDataSource": "USER"
                },
                "minCharactersTrigger": 1
              }
            ]
          }
        }
      ]
    }
  ]
}
ป้อนข้อมูลรายการจากแหล่งข้อมูลภายนอก

หากต้องการป้อนข้อมูลรายการจากแหล่งข้อมูลของบุคคลที่สามหรือแหล่งข้อมูลภายนอก เช่น ระบบการจัดการลูกค้าสัมพันธ์ (CRM) ให้ใช้ช่อง remoteDataSource ภายใน DataSourceConfig เพื่อระบุฟังก์ชันที่แสดงผลรายการจากแหล่งข้อมูล

โค้ดต่อไปนี้แสดงเมนูแบบเลื่อนลงที่สร้างรายการจากชุดรายชื่อติดต่อภายนอกโดยเรียกใช้ฟังก์ชัน 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"
              }
            ]
          }
        }
      ]
    }
  ]
}

หากต้องการลดคำขอไปยังแหล่งข้อมูลแบบไดนามิก คุณสามารถรวมรายการที่แนะนำซึ่งปรากฏในเมนูแบบเลื่อนลงก่อนที่ผู้ใช้จะพิมพ์ได้ นอกจากนี้ คุณยังกำหนดค่าเมนูแบบเลื่อนลงให้เติมข้อความอัตโนมัติในรายการตามสิ่งที่ผู้ใช้พิมพ์ได้โดยตั้งค่า minCharactersTrigger ภายใน DataSourceConfig เมื่อผู้ใช้พิมพ์อักขระอย่างน้อยตามจำนวนที่ระบุใน minCharactersTrigger ระบบจะเรียกใช้ฟังก์ชันที่ระบุใน remoteDataSource ออบเจ็กต์เหตุการณ์ที่ส่งไปยังฟังก์ชันของคุณจะมีข้อมูลที่ผู้ใช้ป้อนในคีย์ autocomplete_widget_query

เพิ่มเมนูแบบเลือกได้หลายรายการ

ตัวอย่างต่อไปนี้แสดงการ์ดที่ขอให้ผู้ใช้เลือกรายชื่อติดต่อจากเมนูแบบเลือกได้หลายรายการ

คุณสามารถป้อนข้อมูลรายการสำหรับเมนูแบบเลือกได้หลายรายการจากแหล่งข้อมูลต่อไปนี้ใน Google Workspace

  • ผู้ใช้ Google Workspace: คุณจะป้อนข้อมูลผู้ใช้ภายในองค์กร Google Workspace เดียวกันได้เท่านั้น
  • พื้นที่ใน Chat: ผู้ใช้ที่ป้อนรายการในเมนูแบบเลือกได้หลายรายการจะดูและเลือกได้เฉพาะพื้นที่ทำงานที่ตนเองเป็นสมาชิกภายในองค์กร Google Workspace เท่านั้น

หากต้องการใช้แหล่งข้อมูล Google Workspace ให้ระบุช่อง platformDataSource คุณจะละเว้นออบเจ็กต์ SelectionItem ได้ ซึ่งแตกต่างจากประเภทอินพุตการเลือกอื่นๆ เนื่องจากรายการที่เลือกเหล่านี้มาจาก Google Workspace แบบไดนามิก

โค้ดต่อไปนี้แสดงเมนูแบบเลือกได้หลายรายการของผู้ใช้ Google Workspace หากต้องการป้อนข้อมูลผู้ใช้ อินพุตการเลือกจะตั้งค่า commonDataSource เป็น USER ดังนี้

JSON

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

โค้ดต่อไปนี้แสดงเมนูแบบเลือกได้หลายรายการของพื้นที่ทำงานใน Chat หากต้องการป้อนข้อมูลในพื้นที่ทำงาน อินพุตการเลือกจะระบุช่อง hostAppDataSource เมนูแบบเลือกได้หลายรายการยังตั้งค่า defaultToCurrentSpace เป็น true ซึ่งทำให้พื้นที่ทำงานปัจจุบันเป็นตัวเลือกเริ่มต้นในเมนูด้วย

JSON

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

เมนูแบบเลือกได้หลายรายการยังสามารถป้อนข้อมูลรายการจากบุคคลที่สามหรือแหล่งข้อมูลภายนอกได้ด้วย เช่น คุณสามารถใช้เมนูแบบเลือกได้หลายรายการเพื่อช่วยให้ผู้ใช้เลือกจากรายการผู้มีโอกาสเป็นลูกค้าจากระบบการจัดการลูกค้าสัมพันธ์ (CRM)

หากต้องการใช้แหล่งข้อมูลภายนอก ให้ใช้ช่อง externalDataSource เพื่อระบุฟังก์ชันที่แสดงผลรายการจากแหล่งข้อมูล

หากต้องการลดคำขอไปยังแหล่งข้อมูลภายนอก คุณสามารถรวมรายการที่แนะนำซึ่งปรากฏในเมนูแบบเลือกได้หลายรายการก่อนที่ผู้ใช้จะพิมพ์ในเมนู เช่น คุณสามารถป้อนข้อมูลรายชื่อติดต่อที่ค้นหาล่าสุดสำหรับผู้ใช้ได้ หากต้องการป้อนข้อมูลรายการที่แนะนำจากแหล่งข้อมูลภายนอก ให้ระบุออบเจ็กต์ SelectionItem

ตัวอย่างโค้ดต่อไปนี้แสดงเมนูแบบเลือกได้หลายรายการที่ค้นหาและป้อนข้อมูลรายการจากแหล่งข้อมูลภายนอก

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

แทนที่ FUNCTION_URL ด้วยปลายทาง HTTP ที่ค้นหาแหล่งข้อมูลภายนอก

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

แทนที่ FUNCTION_URL ด้วยปลายทาง HTTP ที่ค้นหาแหล่งข้อมูลภายนอก

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

แทนที่ FUNCTION_URL ด้วยปลายทาง HTTP ที่ค้นหาแหล่งข้อมูลภายนอก

Apps Script

ตัวอย่างนี้จะส่งข้อความการ์ดโดยแสดงผล JSON ของการ์ด นอกจากนี้ คุณยังใช้บริการการ์ด 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")]
}

ป้อนข้อมูลรายการที่แนะนำจากแหล่งข้อมูลแบบไดนามิก

สำหรับแหล่งข้อมูลภายนอก คุณยังสามารถเติมข้อความอัตโนมัติและแนะนำรายการที่ผู้ใช้เริ่มพิมพ์ในเมนูแบบเลือกหลายรายการหรือเมนูแบบเลื่อนลงได้ด้วย ตัวอย่างเช่น หากผู้ใช้เริ่มพิมพ์ Atl สำหรับเมนูที่แสดงเมืองในสหรัฐอเมริกา แอปใน Chat จะแนะนำ Atlanta โดยอัตโนมัติก่อนที่ผู้ใช้จะพิมพ์เสร็จ คุณแนะนำสินค้าได้สูงสุด 100 รายการ

หากต้องการแสดงรายการที่แนะนำ ฟังก์ชันที่ค้นหาแหล่งข้อมูลภายนอกต้องทำดังนี้

  1. จัดการออบเจ็กต์เหตุการณ์ซึ่งแอปใน Chat จะได้รับเมื่อผู้ใช้พิมพ์ในเมนู
  2. จากออบเจ็กต์เหตุการณ์ ให้รับค่าที่ผู้ใช้พิมพ์ ซึ่งแสดงในช่อง event.commonEventObject.parameters["autocomplete_widget_query"]
  3. ค้นหาแหล่งข้อมูลโดยใช้ค่าที่ผู้ใช้ป้อนเพื่อรับ SelectionItems อย่างน้อย 1 รายการเพื่อแนะนำแก่ผู้ใช้
  4. แสดงรายการที่แนะนำโดยแสดงการดำเนินการ RenderActions พร้อมออบเจ็กต์ modifyCard

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีที่แอปใน Chat แนะนำรายการในเมนูแบบหลายตัวเลือกบนการ์ดแบบไดนามิก เมื่อผู้ใช้พิมพ์ในเมนู ฟังก์ชันหรือปลายทางที่ระบุในช่อง externalDataSource ของวิดเจ็ตจะค้นหาแหล่งข้อมูลภายนอก และแนะนำรายการที่ผู้ใช้เลือกได้ ดังนี้

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

แทนที่ FUNCTION_URL ด้วยปลายทาง HTTP ที่ค้นหาแหล่งข้อมูลภายนอก

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
  }

แทนที่ FUNCTION_URL ด้วยปลายทาง HTTP ที่ค้นหาแหล่งข้อมูลภายนอก

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

แทนที่ FUNCTION_URL ด้วยปลายทาง HTTP ที่ค้นหาแหล่งข้อมูลภายนอก

Apps Script

ตัวอย่างนี้จะส่งข้อความการ์ดโดยแสดงผล JSON ของการ์ด นอกจากนี้ คุณยังใช้บริการการ์ด 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
  };
}

ตรวจสอบข้อมูลที่ป้อนลงในการ์ด

หน้านี้อธิบายวิธีตรวจสอบข้อมูลที่ป้อนลงใน action และวิดเจ็ตของการ์ด เช่น คุณสามารถตรวจสอบว่าช่องป้อนข้อความมีข้อความที่ผู้ใช้ป้อน หรือมีอักขระตามจำนวนที่กำหนด

ตั้งค่าวิดเจ็ตที่จำเป็นสำหรับการดำเนินการ

ในส่วน action ของการ์ด ให้เพิ่มชื่อวิดเจ็ตที่การดำเนินการต้องการลงในรายการ requiredWidgets

หากวิดเจ็ตที่แสดงที่นี่ไม่มีค่าเมื่อมีการเรียกใช้การดำเนินการนี้ ระบบจะยกเลิกการส่งการดำเนินการของแบบฟอร์ม

เมื่อตั้งค่า "allWidgetsAreRequired": true สำหรับการดำเนินการ การดำเนินการนี้จะต้องใช้วิดเจ็ตทั้งหมดในการ์ด

ตั้งค่าการดำเนินการ allWidgetsAreRequired ในการเลือกหลายรายการ

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
              }
            ]
          }
        }
      ]
    }
  ]
}
ตั้งค่าการดำเนินการ allWidgetsAreRequired ใน dateTimePicker

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"
          }
        }
      ]
    }
  ]
}
ตั้งค่าการดำเนินการ allWidgetsAreRequired ในเมนูแบบเลื่อนลง

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

ตั้งค่าการตรวจสอบความถูกต้องสำหรับวิดเจ็ตการป้อนข้อความ

ในช่องการตรวจสอบความถูกต้องของวิดเจ็ต textInput คุณสามารถระบุจำนวนอักขระสูงสุดและประเภทอินพุตสำหรับวิดเจ็ตการป้อนข้อความนี้ได้

กำหนดจำนวนอักขระสูงสุดสำหรับวิดเจ็ตการป้อนข้อความ

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
            }
          }
        }
      ]
    }
  ]
}
ตั้งค่าประเภทอินพุตสำหรับวิดเจ็ตการป้อนข้อความ

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

แก้ปัญหา

เมื่อแอป Google Chat หรือการ์ดแสดงข้อผิดพลาด อินเทอร์เฟซของ Chat จะแสดงข้อความว่า "เกิดข้อผิดพลาด" หรือ "ดำเนินการตามคำขอของคุณไม่ได้" บางครั้ง UI ของ Chat ไม่แสดงข้อความแสดงข้อผิดพลาด แต่แอปใน Chat หรือการ์ดแสดงผลลัพธ์ที่ไม่คาดคิด เช่น ข้อความการ์ดอาจไม่ปรากฏ

แม้ว่าข้อความแสดงข้อผิดพลาดอาจไม่แสดงใน UI ของ Chat แต่ข้อความแสดงข้อผิดพลาดที่สื่อความหมายและข้อมูลบันทึกจะพร้อมใช้งานเพื่อช่วยคุณแก้ไขข้อผิดพลาดเมื่อเปิดการบันทึกข้อผิดพลาดสำหรับแอปใน Chat หากต้องการความช่วยเหลือในการดู แก้ไขข้อบกพร่อง และแก้ไขข้อผิดพลาด โปรดดูหัวข้อแก้ปัญหาและแก้ไขข้อผิดพลาดของ Google Chat

แอปใน Chat ที่ไม่ใช่ส่วนเสริม: ออกแบบการ์ดและกล่องโต้ตอบแบบอินเทอร์แอกทีฟ

เอกสารประกอบต่อไปนี้ใช้กับแอปใน Chat ที่ไม่ใช่ส่วนเสริม Google Workspace หากต้องการย้ายข้อมูลแอป Chat ที่ไม่ใช่ส่วนเสริม โปรดดูหัวข้อแปลงแอป Google Chat เป็นส่วนเสริม Google Workspace

โค้ดต่อไปนี้แสดงเมนูแบบหลายตัวเลือกของรายการจากรายชื่อติดต่อภายนอกสำหรับผู้ใช้ในแอป Chat ที่ไม่ใช่ส่วนเสริม เมนูจะแสดงรายชื่อติดต่อ 1 รายการโดยค่าเริ่มต้น และเรียกใช้ฟังก์ชัน getContacts เพื่อดึงข้อมูลและป้อนข้อมูลรายการจาก แหล่งข้อมูลภายนอก

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

หากต้องการเติมข้อความอัตโนมัติสำหรับรายการในแอปใน Chat ที่ไม่ใช่ส่วนเสริม ให้สร้างฟังก์ชันที่ค้นหาแหล่งข้อมูลภายนอกและแสดงผลรายการเมื่อใดก็ตามที่ผู้ใช้พิมพ์ในเมนูแบบเลือกได้หลายรายการ ฟังก์ชันต้องทำสิ่งต่อไปนี้

  • ส่งออบเจ็กต์เหตุการณ์ที่แสดงถึงการโต้ตอบของผู้ใช้กับเมนู
  • ระบุว่าค่า invokedFunction ของเหตุการณ์การโต้ตอบตรงกับฟังก์ชันจากช่อง externalDataSource
  • เมื่อฟังก์ชันตรงกัน ให้แสดงรายการที่แนะนำจากแหล่งข้อมูลภายนอก หากต้องการแนะนำรายการตามสิ่งที่ผู้ใช้พิมพ์ ให้รับค่าสำหรับคีย์ autocomplete_widget_query ค่านี้แสดงถึงสิ่งที่ผู้ใช้พิมพ์ในเมนู

โค้ดต่อไปนี้จะเติมข้อความอัตโนมัติสำหรับรายการจากแหล่งข้อมูลภายนอก จากตัวอย่างก่อนหน้านี้ แอป Chat ที่ไม่ใช่ส่วนเสริมจะแนะนำรายการโดยอิงตามเวลาที่เรียกใช้ฟังก์ชัน 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);
}

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