עיצוב כרטיס אינטראקטיבי או תיבת דו-שיח

בדף הזה מוסבר איך להוסיף ווידג'טים ורכיבים של ממשק המשתמש להודעות בכרטיס או בתיבת דו-שיח כדי שמשתמשים יוכלו לתקשר עם אפליקציית Google Chat, כמו לחיצה על לחצן או שליחת מידע.


אתם יכולים להשתמש בכלי ליצירת כרטיסים כדי לעצב הודעות של כרטיסי JSON ולהציג אותן בתצוגה מקדימה בשביל אפליקציות ל-Chat:

לפתיחת הכלי ליצירת כרטיסים

דרישות מוקדמות

  • חשבון Google Workspace עם גישה אל Google Chat.
  • אפליקציית Chat שפורסמה. כדי ליצור אפליקציית Chat, אפשר לעקוב אחרי זה מדריך למתחילים.
  • הוספת לחצן

    ווידג'ט ButtonList מציגה קבוצה של לחצנים. לחצנים יכולים להציג טקסט, או גם טקסט וגם סמל. כל אחד Button תומך פעולה אחת (OnClick) שמתרחש כשמשתמשים לוחצים על הלחצן. לדוגמה:

    • פתיחת היפר-קישור באמצעות OpenLink, כדי לספק למשתמשים מידע נוסף.
    • להריץ action שמפעילה פונקציה מותאמת אישית, כמו שליחת קריאה ל-API.

    מטעמי נגישות, הלחצנים תומכים בטקסט חלופי.

    הוספת לחצן שמפעיל פונקציה מותאמת אישית

    הכרטיס הבא מכיל ווידג'ט של ButtonList עם שני לחצנים. לחיצה על לחצן אחד פותחת את מסמכי התיעוד למפתחים של Google Chat בכרטיסייה חדשה. הלחצן האחר מפעיל פונקציה מותאמת אישית בשם goToView() ומעביר את הערך viewType="BIRD EYE VIEW".

    הוספת לחצן עם צבע מותאם אישית ולחצן מושבת

    כדי למנוע ממשתמשים ללחוץ על לחצן, צריך להגדיר "disabled": "true".

    למטה מוצג כרטיס שמכיל ווידג'ט של ButtonList עם הלחצנים. לחצן אחד משתמש שדה אחד (Color) כדי להתאים אישית את הרקע של הלחצן צבע. הלחצן השני מושבת באמצעות השדה Disabled, מונעת מהמשתמש ללחוץ על הלחצן ולבצע את הפונקציה.

    הוספת לחצן עם סמל

    למטה מוצג כרטיס שמורכב מווידג'ט של ButtonList עם שני סמלים Button ווידג'טים. לחצן אחד משתמש knownIcon שדה להצגת סמל האימייל המובנה של Google Chat. הלחצן השני משתמש שדה iconUrl כדי להציג ווידג'ט לסמל מותאם אישית.

    הוספת לחצן עם סמל וטקסט

    למטה מוצג כרטיס שמורכב מווידג'ט של ButtonList המשתמש כדי לשלוח אימייל. הלחצן הראשון מציג סמל אימייל הלחצן השני מציג טקסט. המשתמש יכול ללחוץ על הסמל או על הטקסט כדי להריץ את הפונקציה sendEmail.

    הוספת רכיבים שניתן לבחור בממשק המשתמש

    הווידג'ט SelectionInput מספקת קבוצה של פריטים שניתן לבחור, כמו תיבות סימון, לחצני בחירה, מתגים, או תפריט נפתח. אפשר להשתמש בווידג'ט הזה כדי לאסוף ממשתמשים נתונים מוגדרים וסטנדרטיים. כדי לאסוף נתונים לא מוגדרים של המשתמשים, השתמשו בווידג'ט TextInput במקום זאת.

    הווידג'ט SelectionInput תומך בהצעות שעוזרות למשתמשים להזין מדים נתונים ופעולות לשינוי, שהן Actions שפועלות כשמתרחש שינוי בשדה להזנת קלט, כמו משתמש בחירה או ביטול בחירה של פריט.

    אפליקציות צ'אט יכולות לקבל ולעבד את הערך של הפריטים שנבחרו. לקבלת מידע על עבודה עם קלט טפסים, אפשר לעיין במאמר הבא: עיבוד מידע שמשתמשים מזינים.

    בקטע הזה מפורטות דוגמאות לכרטיסים שנעשה בהם שימוש בווידג'ט SelectionInput. הדוגמאות כוללות סוגים שונים של נתוני קלט של קטעים:

    הוספה של תיבת סימון

    ההודעה הבאה מציגה תיבת דו-שיח שמבקשת מהמשתמש לציין אם הוא איש קשר מקצועי, אישי או שניהם, באמצעות ווידג'ט SelectionInput משתמשת בתיבות סימון:

    הוספת לחצן בחירה

    ההודעה הבאה מציגה תיבת דו-שיח שמבקשת מהמשתמש לציין אם הוא מקצועי או אישי באמצעות ווידג'ט SelectionInput לחצני בחירה:

    הוספת מתג

    ההודעה הבאה מציגה תיבת דו-שיח שמבקשת מהמשתמש לציין אם הוא מקצועי, אישי, או שניהם באמצעות ווידג'ט SelectionInput משתמש במתגים:

    ההודעה הבאה מציגה תיבת דו-שיח שמבקשת מהמשתמש לציין אם הוא מקצועי או אישי באמצעות ווידג'ט SelectionInput תפריט נפתח:

    הוספת תפריט לבחירה מרובה

    למטה מוצגת תיבת דו-שיח שבה המשתמש מתבקש לבחור אנשי קשר מתפריט בחירה מרובה:

    שימוש במקורות נתונים לתפריטים עם ריבוי בחירה

    בקטע הבא מוסבר איך להשתמש בתפריטים עם ריבוי בחירה כדי לאכלס נתונים ממקורות דינמיים, כמו אפליקציה של Google Workspace או נתונים חיצוניים מקור.

    מקורות נתונים מ-Google Workspace

    אפשר לאכלס פריטים בתפריט של בחירה מרובה ממקורות הנתונים הבאים ב- Google Workspace:

    • משתמשי Google Workspace: אפשר לאכלס רק משתמשים בתוך אותו ארגון ב-Google Workspace.
    • מרחבים משותפים ב-Chat: המשתמשים שמזינים פריטים בבחירה מרובה יכולים לראות ולבחור רק מרחבים שהם שייכים אליהם ארגון ב-Google Workspace.

    כדי להשתמש במקורות נתונים של Google Workspace, צריך לציין platformDataSource השדה הזה. בשונה מסוגי קלט אחרים של בחירה, המערכת משמיטת את SectionItem אובייקטים, כי פריטי הבחירה האלה מגיעים באופן דינמי מ- 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
              }
            }
          }
        }
      }
    }
    
    מקורות נתונים מחוץ ל-Google Workspace

    תפריטים לבחירה מרובה יכולים גם לאכלס פריטים מנתונים של צד שלישי או מנתונים חיצוניים מקור. לדוגמה, תוכלו להשתמש בתפריטים עם ריבוי בחירה כדי לעזור למשתמש לבחור מתוך רשימה של לידים למכירות ממערכת לניהול קשרי לקוחות (CRM).

    כדי להשתמש במקור נתונים חיצוני, צריך להשתמש בשדה externalDataSource כדי מציינים פונקציה שמחזירה פריטים ממקור הנתונים.

    כדי לצמצם את הבקשות למקור נתונים חיצוני, אפשר לכלול הצעות לפריטים שמופיעים בתפריט הבחירה מרובה לפני שהמשתמשים מקלידים התפריט. לדוגמה, אפשר לאכלס אנשי קשר שחיפשת לאחרונה עבור משתמש. כדי לאכלס הצעות לפריטים ממקור נתונים חיצוני, צריך לציין SelectionItem אובייקטים.

    הקוד הבא מציג תפריט עם אפשרות בחירה מרובה של פריטים מתוך קבוצה חיצונית של אנשי קשר עבור המשתמש. כברירת מחדל מוצג בתפריט איש קשר אחד ומריצים את הפונקציה getContacts כדי לאחזר ולאכלס פריטים מקור נתונים חיצוני:

    JSON

    {
      "selectionInput": {
        "name": "contacts",
        "type": "MULTI_SELECT",
        "label": "Selected contacts",
        "multiSelectMaxSelectedItems": 5,
        "multiSelectMinQueryLength": 2,
        "externalDataSource": {
          "function": "getContacts"
        },
        "items": [
          {
            "text": "Contact 3",
            "value": "contact-3",
            "startIconUri": "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
            "bottomText": "Contact three description",
            "selected": false
          }
        ]
      }
    }
    

    כשמדובר במקורות נתונים חיצוניים, אפשר גם לבצע השלמה אוטומטית של פריטים שהמשתמשים התחילו. להקלדה בתפריט הבחירה מרובה. לדוגמה, אם משתמש מתחיל להקליד Atl עבור שמאכלס את הערים בארצות הברית, אפליקציית Chat יכולה להציע אוטומטית Atlanta לפני המשתמש מסיים להקליד. אפשר להשלים אוטומטית עד 100 פריטים.

    כדי להשלים באופן אוטומטי פריטים, צריך ליצור פונקציה ששולחת שאילתה על הנתונים החיצוניים ומחזירה פריטים בכל פעם שמשתמש מקליד בתפריט הבחירה מרובה. חייבת לבצע את הפעולות הבאות:

    • מעבירים אובייקט אירוע שמייצג את האינטראקציה של המשתמש עם התפריט.
    • מזהים שאירוע האינטראקציה invokedFunction תואם לפונקציה מהשדה externalDataSource.
    • כשהפונקציות תואמות, מוחזרות פריטים מהנתונים החיצוניים מקור. כדי להציע פריטים בהתאם למה שהמשתמש מקליד, צריך לקבל את הערך של מקש autocomplete_widget_query. הערך הזה מייצג את מה שהמשתמש מקליד בתפריט.

    הקוד הבא משלים באופן אוטומטי פריטים ממשאב נתונים חיצוני. באמצעות מהדוגמה הקודמת, אפליקציית Chat מציעה פריטים על סמך כשהפונקציה getContacts מופעלת:

    Apps Script

    apps-script/selection-input/on-widget-update.gs
    /**
     * Widget update event handler.
     *
     * @param {Object} event The event object from Chat API.
     * @return {Object} Response from the Chat app.
     */
    function onWidgetUpdate(event) {
      const actionName = event.common["invokedFunction"];
      if (actionName !== "getContacts") {
        return {};
      }
    
      return {
        actionResponse: {
          type: "UPDATE_WIDGET",
          updatedWidget: {
            suggestions: {
              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
                },
              ]
            }
          }
        }
      };
    }
    

    Node.js

    node/selection-input/on-widget-update.js
    /**
     * Widget update event handler.
     *
     * @param {Object} event The event object from Chat API.
     * @return {Object} Response from the Chat app.
     */
    function onWidgetUpdate(event) {
      const actionName = event.common["invokedFunction"];
      if (actionName !== "getContacts") {
        return {};
      }
    
      return {
        actionResponse: {
          type: "UPDATE_WIDGET",
          updatedWidget: {
            suggestions: {
              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
                },
              ]
            }
          }
        }
      };
    }
    

    הוספת שדה שבו המשתמש יכול להזין טקסט

    הווידג'ט TextInput מספקת שדה שבו המשתמשים יכולים להזין טקסט. הווידג'ט תומך בהצעות, שעוזרות למשתמשים להזין נתונים אחידים פעולות, Actions שפועלות כשמתרחש שינוי בשדה של קלט הטקסט, כמו משתמש שמוסיף או מחיקת הטקסט.

    אם צריך לאסוף נתונים מופשטים או לא ידועים מהמשתמשים, כדאי להשתמש הווידג'ט TextInput. כדי לאסוף נתונים מוגדרים ממשתמשים, צריך להשתמש SelectionInput במקום זאת.

    כדי לעבד את הטקסט שמשתמשים מזינים: עיבוד מידע שמשתמשים מזינים.

    הכרטיס הבא מורכב מהווידג'ט TextInput:

    משתמש יכול לבחור תאריך ושעה

    ווידג'ט DateTimePicker מאפשרת למשתמשים להזין תאריך, שעה או גם תאריך בו זמנית. לחלופין, המשתמשים יכולים להשתמש בבורר כדי לבחור תאריכים ושעות. אם משתמשים מזינים תאריך או שעה לא חוקיים, הבורר מציג שגיאה שמבקשת מהמשתמשים להזין את המידע בצורה נכונה.

    כדי לעבד את ערכי התאריך והשעה שמשתמשים הזינו: עיבוד מידע שמשתמשים מזינים.

    למטה מוצג כרטיס שמורכב משלושה סוגים שונים של DateTimePicker ווידג'טים:

    אימות הנתונים שהוזנו לכרטיסים

    בדף הזה מוסבר איך לאמת את הנתונים שהוזנו בaction של הכרטיס ווידג'טים. לדוגמה, אפשר לוודא ששדה להזנת קלט טקסט מכיל טקסט שהוזן על ידי משתמש או שהוא מכיל מספר מסוים של תווים.

    הגדרת ווידג'טים נדרשים לפעולות

    כחלק מaction של הכרטיס, הוספת שמות של ווידג'טים שנדרשים לפעולה לרשימת requiredWidgets שלה.

    אם לווידג'טים שמופיעים כאן אין ערך כשהפעולה הזו מופעלת, שליחת הטופס תבוטל.

    אם המדיניות "all_widgets_are_required": "true" מוגדרת לפעולה, כל הווידג'טים בכרטיס, נדרשות פעולות כאלה.

    הגדרת פעולת all_widgets_are_required בבחירה מרובה

    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 ב-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":{
                  "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 בתפריט הנפתח

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

    הגדרת אימות לווידג'ט של קלט טקסט

    בtextInput הוא שדה האימות של הווידג'ט, הוא יכול לציין את מגבלת התווים ואת סוג הקלט הווידג'ט הזה של קלט הטקסט.

    הגדרת מגבלת תווים לווידג'ט של קלט טקסט

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

    הגדרת סוג הקלט לווידג'ט של קלט טקסט

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

    פתרון בעיות

    כשאפליקציית Google Chat או אפליקציית Google Chat הפונקציה card מחזירה שגיאה, בממשק של Chat מוצגת ההודעה "משהו השתבש". או "לא ניתן לעבד את הבקשה שלך". לפעמים בממשק המשתמש של Chat לא מציגה הודעות שגיאה, אבל אפליקציית Chat או והכרטיס מפיק תוצאה לא צפויה: לדוגמה, הודעה בכרטיס יופיעו.

    יכול להיות שלא תופיע הודעת שגיאה בממשק המשתמש של Chat, אבל יש הודעות שגיאה תיאוריות ונתוני יומן זמינים כדי לעזור לכם לתקן שגיאות כשמופעלת רישום שגיאות ביומן של אפליקציות ל-Chat. כדי לקבל עזרה בצפייה, לניפוי באגים ולתיקון שגיאות: פתרון בעיות ותיקון שגיאות ב-Google Chat