如何使提交功能在使用 Google Apps 脚本创建并嵌入到 Google 站点中的 Web 表单中工作?
How to make submission function work in a web form that is created using Google Apps Script and embedded in a Google Site?
我想将使用 Google Apps 脚本创建的网站嵌入到 Google 网站。但是,当表单嵌入 Google 网站(如 this.
时,表单中的数据提交按钮将失效
在网络表单中,表单访问者将数据输入到由index.html
生成的表单中,并在数据提交后看到result.html
。 index.html
中有一个内部的link,用来连接一个header和它的相关内容。当表单应用程序未嵌入任何其他站点时,它可以成功运行。查看the form app,您会发现数据提交按钮可以正常工作。
有人告诉我我错过了什么吗?
MWE
我在 Google Apps 脚本的同一个项目中有四个文件:
index.html
生成表单
JavaScript.html
定义了 index.html
中使用的函数
result.html
表单提交后显示
code.gs
由 doGet()
显示表单,并处理提交的数据并由 doPost()
呈现 result.html
。此文件中定义的 include()
允许将 JavaScript.html
输入到 index.html
index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<!-- <?!= include("css"); ?> -->
</head>
<body onload="addOptions()"> <!--Execute addOptions function immediately after a page has been loaded-->
<form class="" action="<?!= getScriptUrl(); ?>" method="post" onSubmit="document.getElementById('submit').disabled=true;">
<div>
<h1 id="Question">
Choose either cheesecake or chocolate cake.
</h1>
<select id="dropdownList" name="cake" class="form-control">
</select>
</div>
<p>
<div style="width:100px;height:500px;border:1px solid #000;">
Blank box to scroll down
</div>
</p>
<p>
Please do not forget what you've answered in the <a href="#Question" target="_self">question<a>
</p>
<div class="form-submit">
<input type="submit" name="" value="Submit">
</div>
</form>
</body>
<?!= include('JavaScript') ?>
</html>
JavaScript.html
<script>
function addOptions() {
/*This will call server-side Apps Script function getAvailableExps and if it is successful,
it will pass the return value to function addListValues which will add options to the drop down menu*/
google.script.run
.withFailureHandler(onFailure)
.withSuccessHandler(addListValues)
.getAvailableExps();
}
function addListValues(values) {
//Add options to drop down menu using the values of parameter 'values'.
for (var i = 0; i < values.length; i++) {
var option = document.createElement("option");
option.text = values[i][0];
option.value = values[i][0];
var select = document.getElementById("dropdownList");
select.appendChild(option);
}
}
function onFailure(err) {
alert('Error: ' + err.message);
}
</script>
result.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<base />
<title>Thank you for your order!</title>
<!-- <?!= include('css'); ?> -->
</head>
<body>
<p>
Don't forget what you've ordered!
</p>
</body>
</html>
code.gs
var sheetID = "............................................";
var inventory_sheet = "Inventory";
function doGet(){
PropertiesService.getScriptProperties().setProperty("key", "sample");
return HtmlService.createTemplateFromFile("index").evaluate();
}
function include(filename){
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
function getScriptUrl() {
var url = ScriptApp.getService().getUrl();
Logger.log(url);
return url;
}
function doPost(e){
var p = PropertiesService.getScriptProperties();
if (p.getProperty("key") == "sample") {
var ss = SpreadsheetApp.openById(sheetID);
var sh = ss.getSheets()[0];
sh.appendRow([String(e.parameters.cake)]);
//update Inventory
var inventory = ss.getSheetByName(inventory_sheet);
var row = inventory.createTextFinder(e.parameters.cake).findNext().getRow();
var range = inventory.getRange(row, 2);
var data = range.getValue();
range.setValue(parseInt(data - 1))
p.deleteProperty("key");
}
return HtmlService.createTemplateFromFile("result").evaluate();
}
function getAvailableExps(){
var inventory = SpreadsheetApp.openById(sheetID).getSheetByName(inventory_sheet);
var data = inventory.getRange(2, 1, 2, 2).getValues();
var filtered = data.filter(arr => arr[1] > 0 || arr[1] != ''); //remove exp to array if quantity is 0 or empty
return filtered;
}
问题和解决方法:
我认为在你的情况下,你的目标很难用你的展示脚本直接实现。 .
中已经提到了这个原因
当我看到 时,您似乎需要 运行 Google 端的 Web 应用程序。
在这种情况下,我认为可能需要使用变通方法。在这个答案中,为了实现您的目标,我想提出一个解决方法。此解决方法的要点如下。
- 在您的脚本中,
<select id="dropdownList" name="cake" class="form-control"></select>
的值使用表单的 action="<?!= getScriptUrl(); ?>" method="post"
发送到 doPost
。
- 在此解决方法中,使用
google.script.run
将值发送到 Google Apps 脚本。并且,在值完全提交后,HTML 正文被 result.html
. 覆盖
当这一点反映在你的脚本中,就变成了下面这样。
修改后的脚本:
index.html
请修改index.html
如下。
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<!-- <?!= include("css"); ?> -->
</head>
<body id="body" onload="addOptions()">
<form id="form">
<div>
<h1 id="Question">
Choose either cheesecake or chocolate cake.
</h1>
<select id="dropdownList" name="cake" class="form-control">
</select>
</div>
<p>
<div style="width:100px;height:500px;border:1px solid #000;">
Blank box to scroll down
</div>
</p>
<p>
Please do not forget what you've answered in the <a href="#Question" target="_self">question<a>
</p>
<div class="form-submit">
<input type="submit" name="" value="Submit" onclick="sample(this);return false;">
</div>
</form>
</body>
<?!= include('JavaScript') ?>
</html>
JavaScript.html
请在JavaScript.html
中添加以下功能。
function sample(e) {
const f = document.getElementById("form");
const obj = { parameters: [...f].reduce((o, g) => (o[g.name] = [g.value], o), {}) };
google.script.run
.withSuccessHandler((res) => {
document.getElementById("body").innerHTML = res;
})
.sample(obj);
}
- 在此示例脚本中,为了直接使用您的
doPost
,准备了 obj
的值。请注意这一点。
Code.gs
:Google Apps 脚本端
请将以下功能添加到Code.gs
。此功能使用您的 doPost
.
function sample(e) {
return doPost(e).getContent();
}
测试:
当此修改反映在您的脚本中并且您的 Web 应用程序嵌入到 Google 站点时,单击提交按钮时,cake
的值将发送到 Google Apps 脚本端并显示 result.html
。我以为这种情况可能是你期望的结果。
注:
此修改是一个简单的修改,用于解释解决方法。所以,请根据您的实际情况进行修改。
当您修改 Google Apps 脚本时,请将部署修改为新版本。这样,修改后的脚本就会反映在 Web Apps 中。请注意这一点。
你可以在“Redeploying Web Apps without Changing URL of Web Apps for new IDE”的报告中看到详细信息。
关于Google站点Web Apps的内部link,似乎当Web Apps的while页面被嵌入且滚动条不显示时,内部 link 不起作用。当显示框架的滚动条时,link 起作用。在这种情况下,内部 link 似乎无法同时使用 HTML 和 Javascript。而且,我无法确认错误消息。
我想将使用 Google Apps 脚本创建的网站嵌入到 Google 网站。但是,当表单嵌入 Google 网站(如 this.
时,表单中的数据提交按钮将失效在网络表单中,表单访问者将数据输入到由index.html
生成的表单中,并在数据提交后看到result.html
。 index.html
中有一个内部的link,用来连接一个header和它的相关内容。当表单应用程序未嵌入任何其他站点时,它可以成功运行。查看the form app,您会发现数据提交按钮可以正常工作。
有人告诉我我错过了什么吗?
MWE
我在 Google Apps 脚本的同一个项目中有四个文件:
index.html
生成表单JavaScript.html
定义了index.html
中使用的函数
result.html
表单提交后显示code.gs
由doGet()
显示表单,并处理提交的数据并由doPost()
呈现result.html
。此文件中定义的include()
允许将JavaScript.html
输入到index.html
index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<!-- <?!= include("css"); ?> -->
</head>
<body onload="addOptions()"> <!--Execute addOptions function immediately after a page has been loaded-->
<form class="" action="<?!= getScriptUrl(); ?>" method="post" onSubmit="document.getElementById('submit').disabled=true;">
<div>
<h1 id="Question">
Choose either cheesecake or chocolate cake.
</h1>
<select id="dropdownList" name="cake" class="form-control">
</select>
</div>
<p>
<div style="width:100px;height:500px;border:1px solid #000;">
Blank box to scroll down
</div>
</p>
<p>
Please do not forget what you've answered in the <a href="#Question" target="_self">question<a>
</p>
<div class="form-submit">
<input type="submit" name="" value="Submit">
</div>
</form>
</body>
<?!= include('JavaScript') ?>
</html>
JavaScript.html
<script>
function addOptions() {
/*This will call server-side Apps Script function getAvailableExps and if it is successful,
it will pass the return value to function addListValues which will add options to the drop down menu*/
google.script.run
.withFailureHandler(onFailure)
.withSuccessHandler(addListValues)
.getAvailableExps();
}
function addListValues(values) {
//Add options to drop down menu using the values of parameter 'values'.
for (var i = 0; i < values.length; i++) {
var option = document.createElement("option");
option.text = values[i][0];
option.value = values[i][0];
var select = document.getElementById("dropdownList");
select.appendChild(option);
}
}
function onFailure(err) {
alert('Error: ' + err.message);
}
</script>
result.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<base />
<title>Thank you for your order!</title>
<!-- <?!= include('css'); ?> -->
</head>
<body>
<p>
Don't forget what you've ordered!
</p>
</body>
</html>
code.gs
var sheetID = "............................................";
var inventory_sheet = "Inventory";
function doGet(){
PropertiesService.getScriptProperties().setProperty("key", "sample");
return HtmlService.createTemplateFromFile("index").evaluate();
}
function include(filename){
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
function getScriptUrl() {
var url = ScriptApp.getService().getUrl();
Logger.log(url);
return url;
}
function doPost(e){
var p = PropertiesService.getScriptProperties();
if (p.getProperty("key") == "sample") {
var ss = SpreadsheetApp.openById(sheetID);
var sh = ss.getSheets()[0];
sh.appendRow([String(e.parameters.cake)]);
//update Inventory
var inventory = ss.getSheetByName(inventory_sheet);
var row = inventory.createTextFinder(e.parameters.cake).findNext().getRow();
var range = inventory.getRange(row, 2);
var data = range.getValue();
range.setValue(parseInt(data - 1))
p.deleteProperty("key");
}
return HtmlService.createTemplateFromFile("result").evaluate();
}
function getAvailableExps(){
var inventory = SpreadsheetApp.openById(sheetID).getSheetByName(inventory_sheet);
var data = inventory.getRange(2, 1, 2, 2).getValues();
var filtered = data.filter(arr => arr[1] > 0 || arr[1] != ''); //remove exp to array if quantity is 0 or empty
return filtered;
}
问题和解决方法:
我认为在你的情况下,你的目标很难用你的展示脚本直接实现。
当我看到
在这种情况下,我认为可能需要使用变通方法。在这个答案中,为了实现您的目标,我想提出一个解决方法。此解决方法的要点如下。
- 在您的脚本中,
<select id="dropdownList" name="cake" class="form-control"></select>
的值使用表单的action="<?!= getScriptUrl(); ?>" method="post"
发送到doPost
。 - 在此解决方法中,使用
google.script.run
将值发送到 Google Apps 脚本。并且,在值完全提交后,HTML 正文被result.html
. 覆盖
当这一点反映在你的脚本中,就变成了下面这样。
修改后的脚本:
index.html
请修改index.html
如下。
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<!-- <?!= include("css"); ?> -->
</head>
<body id="body" onload="addOptions()">
<form id="form">
<div>
<h1 id="Question">
Choose either cheesecake or chocolate cake.
</h1>
<select id="dropdownList" name="cake" class="form-control">
</select>
</div>
<p>
<div style="width:100px;height:500px;border:1px solid #000;">
Blank box to scroll down
</div>
</p>
<p>
Please do not forget what you've answered in the <a href="#Question" target="_self">question<a>
</p>
<div class="form-submit">
<input type="submit" name="" value="Submit" onclick="sample(this);return false;">
</div>
</form>
</body>
<?!= include('JavaScript') ?>
</html>
JavaScript.html
请在JavaScript.html
中添加以下功能。
function sample(e) {
const f = document.getElementById("form");
const obj = { parameters: [...f].reduce((o, g) => (o[g.name] = [g.value], o), {}) };
google.script.run
.withSuccessHandler((res) => {
document.getElementById("body").innerHTML = res;
})
.sample(obj);
}
- 在此示例脚本中,为了直接使用您的
doPost
,准备了obj
的值。请注意这一点。
Code.gs
:Google Apps 脚本端
请将以下功能添加到Code.gs
。此功能使用您的 doPost
.
function sample(e) {
return doPost(e).getContent();
}
测试:
当此修改反映在您的脚本中并且您的 Web 应用程序嵌入到 Google 站点时,单击提交按钮时,cake
的值将发送到 Google Apps 脚本端并显示 result.html
。我以为这种情况可能是你期望的结果。
注:
此修改是一个简单的修改,用于解释解决方法。所以,请根据您的实际情况进行修改。
当您修改 Google Apps 脚本时,请将部署修改为新版本。这样,修改后的脚本就会反映在 Web Apps 中。请注意这一点。
你可以在“Redeploying Web Apps without Changing URL of Web Apps for new IDE”的报告中看到详细信息。
关于Google站点Web Apps的内部link,似乎当Web Apps的while页面被嵌入且滚动条不显示时,内部 link 不起作用。当显示框架的滚动条时,link 起作用。在这种情况下,内部 link 似乎无法同时使用 HTML 和 Javascript。而且,我无法确认错误消息。