I created a web form using Google Apps Script, where form visitors would see result.html
after data submission. However, the data may be submitted multiple times if visitors reload the result.html
by pressing F5, Ctrl R, ignoring the alert of resubmission. The same concern has already been posted here, and I tried implementing one of the solutions for that, but in vain.
I have now four files in the same project of Google Apps Script:
index.html
that produces the formJavaScript.html
that defines functions used inindex.html
result.html
that is presented after the form submissioncode.gs
that shows the form bydoGet()
, and processes the submitted data and presentsresult.html
bydoPost()
.include()
defined in this file enables to inputJavaScript.html
intoindex.html
The solution I have tried is adding the following JavaScript code result.html
. I also add that to JavaScript.html
so that the code is to be executed in index.html
, too.
<script>
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
</script>
However, the resubmission still occurs when I reload the result.html
even after I added that code to both result.html
and index.html
. What am I missing?
index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<!-- <?!= include("css"); ?> -->
</head>
<body onl oad="addOptions()"> <!--Execute addOptions function immediately after a page has been loaded-->
<form 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" >
</select>
</div>
<div >
<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);
}
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
</script>
result.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<base />
<title>Thank you for your order!</title>
<!-- <?!= include('css'); ?> -->
</head>
<script>
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}
</script>
<body>
<p>
Don't forget what you've ordered!
</p>
</body>
</html>
code.gs
var sheetID = "............................................";
var inventory_sheet = "Inventory";
function doGet(){
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 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))
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;
}
CodePudding user response:
In your situation, how about checking the submit using PropertiesService? When your script is modified, it becomes as follows.
Modified script:
In this modification, 2 functions of doGet
and doPost
of code.gs
are modified.
doGet
function doGet() {
PropertiesService.getScriptProperties().setProperty("key", "sample");
return HtmlService.createTemplateFromFile("index").evaluate();
}
doPost
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();
}
- When you access to your Web Apps,
sample
is stored bysetProperty("key", "sample")
indoGet()
. And, when the HTML form is submitted, the PropertiesService is checked indoPost(e)
. Whensample
is existing, the data is put, and the PropertiesService is cleared. By this, even when the submitted page is reopened, the PropertiesService is not existing. By this, the resubmitted can be avoided.