1

I am writing my firs add-on for Google Calendar and I am having troubles getting the values from input field, or date pickers.

I've created a card with couple of date pickers (event start date and end date), a text input (for events title), and a button. What I want to do is after clicking a button I would like to get the entered value of the text input and (for now) log it.

This is what I've got:

var card = CardService.newCardBuilder();
var textInputTitle = CardService.newTextInput()
    .setFieldName("text_input_title")
    .setTitle("Title for editor");

function onHomepage(e) {
  return createCard(e.hostApp, true);
}

function createCard(text) {

// Create action button for submitting entered data
  var action = CardService.newAction()
      .setFunctionName('onCreateEvent')
      .setParameters({text: text});
  var button = CardService.newTextButton()
      .setText('Create event')
      .setOnClickAction(action)
      .setTextButtonStyle(CardService.TextButtonStyle.FILLED);
  var buttonSet = CardService.newButtonSet()
      .addButton(button);

  var startDateTimePicker = CardService.newDateTimePicker()
    .setTitle("Event start date")
    .setFieldName("date_time_field_start")
    .setValueInMsSinceEpoch(new Date().getTime())
    .setTimeZoneOffsetInMins(+2 * 60)
    .setOnChangeAction(CardService.newAction()
    .setFunctionName("handleDateTimeChange"));

  var endDateTimePicker = CardService.newDateTimePicker()
    .setTitle("Event end date")
    .setFieldName("date_time_field_end")
    .setValueInMsSinceEpoch(new Date().getTime())
    .setTimeZoneOffsetInMins(+2 * 60)
    .setOnChangeAction(CardService.newAction()
    .setFunctionName("handleDateTimeChange"));


  var section = CardService.newCardSection().setHeader("I am section header")
      .addWidget(startDateTimePicker)
      .addWidget(endDateTimePicker)
      .addWidget(textInputTitle)
      .addWidget(buttonSet);

  card.addSection(section);
  return card.build();
  } 

function onCreateEvent(e){
  Logger.log("Text input%s ",JSON.stringify(e) );
}

I've tried to log the textInputs value but all I get is null. Also I checked the Google app script,gmail addon get TextInput value where a similar problem is solved, but I can't figure out where e.formInput is coming from.

UPDATE adding my manifest file

{
  "timeZone": "America/New_York",
  "dependencies": {
    "enabledAdvancedServices": [{
      "userSymbol": "Calendar",
      "serviceId": "calendar",
      "version": "v3"
    }]
  },
  "exceptionLogging": "STACKDRIVER",
  "oauthScopes": ["https://www.googleapis.com/auth/calendar.addons.execute",
                  "https://www.googleapis.com/auth/calendar", 
                  "https://www.googleapis.com/auth/script.locale"
                 ],
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "event creator",
      "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/calendar_today_black_48dp.png",
      "useLocaleFromApp": true,
      "homepageTrigger": {
        "runFunction": "onHomepage",
        "enabled": true
      }
    },
    "calendar": {
      "eventOpenTrigger": {
        "runFunction": "onCalendarEventOpen"
      }
    }
  }
}
Rafa Guillermo
  • 14,474
  • 3
  • 18
  • 54
SmallDev
  • 23
  • 4

2 Answers2

2

Problem

Accessing formInput / formInputs property on the event object.

Event handling

To understand where the formInputs prop lives, you need to get a grasp on how Add-on handle events:

  1. Every widget class that can be interacted with can be assigned an Action instance;
  2. Action has a callback (set by setFunctionName()) that executes when the action is triggered;
  3. When an action is triggered, an event object is constructed and passed to the function assigned to Action as its first argument.
  4. This event object contains metadata, custom parameters passed to the callback (added by setParameters()), and the desired formInput and formInputs fields.

Applied to the question

If I understood the intention of your code correctly, you will have access to the submitted data when the onCreateEvent(e) is called after the button is pressed. Note that DateTimePickers return their values as nested objects.

References

  1. Add-on actions guide
  2. Event object reference

Notes

  1. You can chain callbacks and pass the event object around as much as you want (be sure to return a response in under 30s, though, or you will timeout), see one of my older answers to a similar question.
  2. The event object will not be populated until the callback is called, so you can't run or debug it from editor or locally (unless you simply mock the event object - it is well-documented)
1

Change Logger.log("Text input%s ",JSON.stringify(e.formInput.text_input_title)); for console.log("Text input%s ",JSON.stringify(e.formInput.text_input_title));:

The logger was not displaying anything so changing it to the console log was the solution. To see the console log once you have created the event you have to go to the Script editor an go to view -> Stackdriver Logging -> Apps Script Dashboard and there you will see the last execution made and the result of the console log (the log may take a few seconds to appear):

enter image description here

As you can see the result is a JSON like:

{ 
   "clientPlatform":"web",
   "userLocale":"en",
   "parameters":{ 
      "text":"calendar"
   },
   "userTimezone":{ 
      "offSet":"3600000",
      "id":"Europe/Madrid"
   },
   "formInputs":{ 
      "date_time_field_end":[ 
         { 
            "hasDate":true,
            "hasTime":true,
            "msSinceEpoch":1581478200000
         }
      ],
      "date_time_field_start":[ 
         { 
            "msSinceEpoch":1581516320343,
            "hasDate":true,
            "hasTime":true
         }
      ],
      "text_input_title":[ 
         "This is a test title"
      ]
   },
   "formInput":{ 
      "date_time_field_end":{ 
         "hasTime":true,
         "msSinceEpoch":1581478200000,
         "hasDate":true
      },
      "date_time_field_start":{ 
         "hasDate":true,
         "hasTime":true,
         "msSinceEpoch":1581516320343
      },
      "text_input_title":"This is a test title"
   },
   "hostApp":"calendar",
   "userCountry":"",
   "commonEventObject":{ 
      "parameters":{ 
         "text":"calendar"
      },
      "platform":"WEB",
      "formInputs":{ 
         "date_time_field_end":{ 
            "dateTimeInput":{ 
               "hasTime":true,
               "msSinceEpoch":1581478200000,
               "hasDate":true
            }
         },
         "date_time_field_start":{ 
            "dateTimeInput":{ 
               "hasDate":true,
               "hasTime":true,
               "msSinceEpoch":1581516320343
            }
         },
         "text_input_title":{ 
            "stringInputs":{ 
               "value":[ 
                  "This is a test title"
               ]
            }
         }
      },
      "hostApp":"CALENDAR",
      "timeZone":{ 
         "id":"Europe/Madrid",
         "offset":3600000
      },
      "userLocale":"en"
   },
   "calendar":{ 

   }
}

So now if we console log -> console.log("Text input",JSON.stringify(e.formInput.text_input_title)); we can see:

enter image description here

Kessy
  • 1,894
  • 1
  • 8
  • 15
  • Thank you so much for showing this! I was looking for so long just to be able to look into the event object I am passing. I thought Logger IS the substitute for console.log in Apps script. – SmallDev Feb 12 '20 at 18:40