It's now easier than ever to use Google Drive Picker in Apps Script with the new <drive-picker>
web component, https://github.com/googleworkspace/drive-picker-element.
Steps
Project settings
If you are only using the picker with drive
or drive.readonly
you can skip to the next section.
The primary requirement is a Google Cloud Project which will be associated with the drive.file
scope. The Cloud project number should also be set on your Apps Script project. See these instructions for details and the screenshot below.
The above steps can be skipped if you are using the drive
or drive.readonly
steps.
Apps Script server functions
The Apps Script server side has two primary functions in this basic demo, doGet()
and handler(event)
. The doGet()
is a special function that can return HTML and evaluate a basic template language.
function doGet() {
const template = HtmlService.createTemplateFromFile("Index");
// drive or drive.file scope set in appsscript.json
template.oauthToken = ScriptApp.getOAuthToken();
// Cloud project number must also be
// set for the Apps Script project
// if using `drive.file` scope
template.appId = 246724281745;
return template.evaluate();
}
The above function gets the HTML content to the user, the following function listens to events sent from the client based upon user interactions with the Picker dialog.
/**
* Handles the Drive Picker event on the server.
*
* @param {CustomEvent} - event passed from `drive-picker` element
* @return {CustomEvent|DriveApp.File}
*/
function eventHandler({ type, detail }) {
console.log({ type, detail });
switch (type) {
case "picker:picked":
// DriveApp doesn't work with drive.file scope
return Drive.Files.get(detail.docs[0].id);
default:
// echo back event
return { type, detail };
}
}
HTML template and JavaScript
The entire HTML file has the following contents.
<!DOCTYPE html>
<html>
<head>
<!--
See available versions at
https://unpkg.com/@googleworkspace/drive-picker-element/
-->
<script src="https://unpkg.com/@googleworkspace/drive-picker-element@0/dist/index.iife.min.js"></script>
<script>
/**
* Handles events from the drive-picker element and sends them to the server
* @param {CustomEvent} event - The event object from the drive-picker.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent
*/
async function eventHandler({ type, detail }) {
console.log({ type, detail });
const response = await new Promise((resolve, reject) => {
// Sends the event data to the server using google.script.run.
// https://developers.google.com/apps-script/guides/html/communication
google.script.run
.withSuccessHandler(resolve)
.withFailureHandler(reject)
.eventHandler({ type, detail });
});
console.log({ response });
}
// Initializes the drive-picker element after the DOM content is loaded.
document.addEventListener("DOMContentLoaded", function () {
const picker = document.createElement("drive-picker");
picker.setAttribute("oauth-token", "<?= oauthToken ?>");
picker.setAttribute("app-id", "<?= appId ?>");
picker.setAttribute("origin", google.script.host.origin);
const view = document.createElement("drive-picker-docs-view");
view.setAttribute("owned-by-me", "true");
picker.appendChild(view);
// see https://github.com/googleworkspace/drive-picker-element
// for more information on additional attributes and views
// see https://developers.google.com/drive/picker/reference/picker
// for Drive Picker reference docs
for (const eventName of [
"picker:picked",
"picker:canceled",
"picker:error",
]) {
picker.addEventListener(eventName, eventHandler);
}
document.body.appendChild(picker);
});
</script>
</head>
<body></body>
</html>
This HTML renders the custom element as the following:
<drive-picker
oauth-token="ya29.OMITTED"
app-id="246724281745"
origin="https://script.google.com"
aria-hidden="true"
><drive-picker-docs-view owned-by-me="true"></drive-picker-docs-view
></drive-picker>
The origin, which corresponds to google.picker.PickerBuilder.setOrigin()
, is required because of the multiple iFrames and can use the client side JavaScript object, google.script.host.origin
.
Deploy and run
When you run this app, the Picker dialog will open!
The above code is implemented to pass the events to the Apps Script server using google.script.run
. When running this code, the events and response from the server for the picker:picked
event look like the following.
{
"type": "picker:picked",
"detail": {
"action": "picked",
"viewToken": [
"all",
null,
{
"ownedByMe": true
}
],
"docs": [
{
"id": "OMITTED",
"serviceId": "DoclistBlob",
"mimeType": "application/pdf",
"name": "OMITTED",
"description": "",
"type": "file",
"lastEditedUtc": 2086003696000,
"iconUrl": "https://drive-thirdparty.googleusercontent.com/16/type/application/pdf",
"url": "https://drive.google.com/file/d/OMITTED/view?usp=drive_web",
"embedUrl": "https://drive.google.com/file/d/OMITTED/preview?usp=drive_web",
"driveSuccess": true,
"sizeBytes": 95211,
"parentId": "OMITTED",
"organizationDisplayName": "Google.com"
}
]
}
}
To confirm the file access, the handler
function calls the Drive Advanced Service and returns basic information about the file to the client using Drive.Files.get(detail.docs[0].id);
// response
{
"response": {
"name": "OMITTED",
"mimeType": "application/pdf",
"id": "OMITTED",
"kind": "drive#file"
}
}
Instead of just returning metadata, you could incorporate this into other business processes or use Gemini and VertexAI!
Checkout the <drive-picker>
element at https://github.com/googleworkspace/drive-picker-element.
Top comments (0)