Building interactive cards

Most add-ons, in addition to presenting data, require the user to enter information. When you build a card-based add-on, you can use interactive widgets such as buttons, toolbar menu items, or checkboxes to ask the user for data that your add-on needs or provide other interaction controls.

Adding actions to widgets

For the most part, you make widgets interactive by linking them to specific actions and implementing the required behavior in a callback function. See add-on actions for details.

In most cases, you can follow this general procedure to configure a widget to take a specific action when selected or updated:

  1. Create an Action object, specifing the callback function that should execute, along with any required parameters.
  2. Link the widget to the Action by calling the appropriate widget handler function.
  3. Implement the callback function to enact the required behavior.

Example

The following example sets a button that displays a user notification after it is clicked. The click triggers the notifyUser() callback function with an argument that specifies the notification text. Returning a built ActionResponse results in a displayed notification.

  /**
   * Build a simple card with a button that sends a notification.
   * @return {Card}
   */
  function buildSimpleCard() {
    var buttonAction = CardService.newAction()
        .setFunctionName('notifyUser')
        .setParameters({'notifyText': 'Button clicked!'});
    var button = CardService.newTextButton()
        .setText('Notify')
        .setOnClickAction(buttonAction);

    // ...continue creating widgets, then create a Card object
    // to add them to. Return the built Card object.
  }

  /**
   * Callback function for a button action. Constructs a
   * notification action response and returns it.
   * @param {Object} e the action event object
   * @return {ActionResponse}
   */
  function notifyUser(e) {
    var parameters = e.parameters;
    var notificationText = parameters['notifyText'];
    return CardService.newActionResponseBuilder()
        .setNotification(CardService.newNotification()
            .setText(notificationText))
        .build();      // Don't forget to build the response!
  }

Design effective interactions

When designing interactive cards, keep the following in mind:

  • Interactive widgets usually need at least one handler method to define their behavior.

  • Use the setOpenLink() widget handler function when you have a URL and just want to open it in a tab. This avoids the need to define an Action object and callback function. If you need to build the URL first, or take any other additional steps before opening the URL, define an Action and use setOnClickOpenLinkAction() instead.

  • When using the setOpenLink() or setOnClickOpenLinkAction() widget handler functions, you need to provide an OpenLink object to define which URL to open. You can also use this object to specify opening and closing behavior using the OpenAs and OnClose enums.

  • It is possible for more than one widget to use the same Action object. However, you need to define different Action objects if you want to provide the callback function different parameters.

  • Keep your callback functions simple. To keep the add-ons responsive, the Card service limits callback functions to a maximum of 30 seconds of execution time. If the execution takes longer than that, your add-on UI may not update its card display properly in response to the Action .

  • If a data status on a third-party backend changes as the result of a user interaction with your add-on UI, it is recommended that the add-on set a 'state changed' bit to true so that any existing client side cache is cleared. See the ActionResponseBuilder.setStateChanged() method description for additional details.