在Google Apps脚本中,如何通过重新加载Dopost()返回的HTML来防止多次提交表单数据?

发布于 2025-01-31 16:53:35 字数 5258 浏览 3 评论 0原文

我使用Google Apps脚本创建了一个Web表单,在数据提交数据后,表单访问者将在其中看到result.html。但是,如果访问者重新加载result.html,可以多次提交数据>,忽略重新提取的警报。同样的问题已经发布在这里,我尝试实现解决方案之一为此,但徒劳无功。

现在,我在Google Apps脚本的同一项目中有四个文件:

  1. index.html 产生表单
  2. javascript.html 强>定义index.html中使用的函数
  3. result.html 在表单提交
  4. code.gs 之后呈现出现 通过doget()显示表单,并处理提交的数据和呈现restect.html by dopost()代码>。 inclage()在此文件中定义的允许输入javascript.html in index.html

我尝试过的解决方案是添加以下Javascript代码<代码> result.html 。我还将其添加到javascript.html中,以便在index.html中执行代码。

<script>
    if ( window.history.replaceState ) {
        window.history.replaceState( null, null, window.location.href );
    }
</script>

但是,即使我将代码添加到result.htmlindex.html之后,即使我在result.html中重新加载 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>

      <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);
  }

  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;
}

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:

  1. index.html that produces the form
  2. JavaScript.html that defines functions used in index.html
  3. result.html that is presented after the form submission
  4. code.gs that shows the form by doGet(), and processes the submitted data and presents result.html by doPost(). include() defined in this file enables to input JavaScript.html into index.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 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>

      <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);
  }

  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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

温柔女人霸气范 2025-02-07 16:53:35

在您的情况下,如何使用alteriesservice检查提交?修改脚本时,如下。

修改后的脚本:

在此修改中,修改了dogetdopost code.gs的2个功能。

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();
}
  • 访问Web应用程序时,示例setproperty(“键”,“ sample”)存储代码>在doget()中。并且,当提交HTML表单时,将在dopost(e)中检查属性。当存在示例时,将放置数据,并清除属性。这样,即使已重新打开了提交的页面,属性也不存在。这样,可以避免重新提交的。

参考:

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 by setProperty("key", "sample") in doGet(). And, when the HTML form is submitted, the PropertiesService is checked in doPost(e). When sample 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.

Reference:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文