I'm converting a script of mine to be an add on. One of the needs is to configure a template, so I have programmed a sidebar that launchs a field picker. As the sidebar does not have enough room for the picker, I have to launch it from a modal dialog that I create from the sidebar, by calling this code in the server side:
var html = HtmlService.createHtmlOutputFromFile('TemplatePicker.html')
.setWidth(600).setHeight(425);
SpreadsheetApp.getUi().showModalDialog(html, 'Select the file with the template');
My problem is that once the user picks the file, when I have the id of the chosen file, I'm not able to pass that id to the sidebar. I tried invoking someJSFunctionOfSidebar(id)
and parent.someJSFunctionOfSidebar(id)
, but it didn't work, so I finally ended passing the value to the server side and reloading the sidebar from there, but it's very slow and the resulting effect is ugly.
My question is:
Is there a way to pass a value at client level from a modal dialog created with SpreadsheetApp.getUi().showModalDialog
to its parent? Perhaps it's not really its parent and that's the reason for it not working.
Perhaps it's not really its parent and that's the reason for it not working.
Right - there isn't actually a DOM parent / child relationship in play here. Both the sidebar and the modal dialog were launched from server-side scripts, and are independent. They can both communicate with the server, though, so you can use a store-and-forward technique to get the result from your picker to the sidebar.
Basic idea:
google.script.run
.Have a look at How to poll a Google Doc from an add-on for the basic idea of a poller.
Sidebar and modal dialog(siblings) are not able to communicate despite having same origin.
It is possible to get a reference to the sidebar html from modal dialog through the ancestor parent window.top
, even though the parent is cross origin. From there, it is possible to
window.postMessage()
to communicate with each otherWithout a reference to each other, it is still possible to communicate with each other through
window.top
):addOn.html[Sidebar]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>Addon</title>
<style>
#spinner {
display: none;
background-color: tomato;
position: absolute;
top: 1%;
width: 100%;
justify-items: center;
}
</style>
</head>
<body>
<div id="spinner"><p>Loading modal dialog...</p></div>
<div id="output"></div>
<script charset="utf-8">
google.script.run.withSuccessHandler(spinner).testModal();
function spinner(e) {
document.getElementById('spinner').style.display = e || 'flex';
}
(async () => {
//After modal dialog has finished, receiver will be resolved
let receiver = new Promise((res, rej) => {
window.modalDone = res;
});
var message = await receiver;
document.querySelector('#output').innerHTML = message;
//Do what you want here
})();
</script>
</body>
</html>
modalAddOn.html[Modal dialog/picker]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title></title>
</head>
<body>
Modal Dialog
<script>
(function findSideBar(limit) {
let f = window.top.frames;
for (let i = 0; i < limit; ++i) {
try {
if (
f[i] /*/iframedAppPanel*/ &&
f[i].length &&
f[i][0] && //#sandboxFrame
f[i][0][0] && //#userHtmlFrame
window !== f[i][0][0] //!== self
) {
console.info('Sidebar found ');
alert('Removing loadbar and closing self');
var sidebar = f[i][0][0];
sidebar.spinner('none'); //Remove sidebar spinner
sidebar.modalDone('Modal says Hi'); //Modal has finished
google.script.host.close();
}
} catch (e) {
console.error(e);
continue;
}
}
})(10);
</script>
</body>
</html>
code.gs[Server]
function testModal() {
SpreadsheetApp.getUi().showModelessDialog(
HtmlService.createHtmlOutputFromFile('modalAddOn')
.setHeight(500)
.setWidth(300),
' '
);
}
function onOpen(e) {
SpreadsheetApp.getUi()
.createMenu('Sidebar')
.addItem('Show Add-On', 'showSidebar')
.addToUi();
}
function showSidebar() {
SpreadsheetApp.getUi().showSidebar(
HtmlService.createTemplateFromFile('addOn.html').evaluate()
);
}
Where is my iframe in the published web application/sidebar?
Window#postMessage
Window#storage
Origin
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With