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

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


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

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

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

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

    בווידג'ט 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 או כרטיס מחזירים שגיאה, מוצגת בממשק של Chat ההודעה "משהו השתבש". או "לא ניתן לעבד את הבקשה שלך". לפעמים לא מוצגות הודעות שגיאה בממשק המשתמש של Chat, אבל האפליקציה או הכרטיס של Chat יוצרים תוצאה לא צפויה. למשל, יכול להיות שלא תופיע הודעת כרטיס.

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