【问题标题】:passing variables to a function with onclick in a forEach loop - Google Apps Script在 forEach 循环中使用 onclick 将变量传递给函数 - Google Apps 脚本
【发布时间】:2020-06-19 22:21:17
【问题描述】:

我正在尝试构建一个网络应用程序,用于从电子表格中收集表格的内容。因此,我将电子表格的内容放在一个数组中,并使用 forEach 循环在 JavaScript 中构建表格。这一切正常,但我希望每一行的一个单元格是可点击的。单击单元格时,我想调用另一个 javascript 函数并将相应行中其他单元格的内容作为变量传递。 我通过在单元格中添加一个链接来使用 onclick 事件调用该函数来做到这一点。当我单击单元格时,我会在控制台日志中看到该函数已被调用,但我想要传递的变量未定义。

我认为问题在于,当单击单元格时,循环结束并且不再定义变量。但我完全不知道这个问题的解决方法。

我的带有 javascript 代码的 HTML 文件(我说的是 //Table JS 部分中的 else,几乎在代码的末尾):

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">

    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">

     <style>
      table.centered {
        table-layout: fixed;
        width: 100%;
      }
      td {
       width: 25%;
      }
      div.add-form{
       width: 50%;
      }
    </style>

  </head>
  <body>
    <h1>Buch hinzufügen</h1>
    <div class="add-form">
      <label>Buchtitel: </label><input type="text" id="titel" class="eingabefeld"> <br>
      <label>Buchautor: </label><input type="text" id="autor" class="eingabefeld"> <br>
      <label>Auflage: </label><input type="number" id="auflage" class="eingabefeld"> <br>
      <button id="btn">Hinzufügen</button>
    </div>

    <!-- Tabelle Buchliste -->
     <h1>Buchliste</h1>

        <table class="centered">
        <thead>
          <tr bgcolor="#f0f0f0">
              <th>Buchtitel</th>
              <th>Buchautor</th>
              <th>Auflage</th>
              <th>Status</th>
          </tr>
        </thead>

        <tbody id="table-body">

        </tbody>
      </table>

    <script>

    //Buch hinzufügen JS
    document.getElementById("btn").addEventListener("click",doStuff);

    function doStuff(){
      var titel =  document.getElementById("titel").value;
      var autor =  document.getElementById("autor").value;
      var auflage =  document.getElementById("auflage").value; 

      //validateForm
      if (titel == "" || autor=="" || auflage=="") {
        alert("FEHLER: Alle Felder müssen ausgefüllt sein!");
        return false;
      }

      //passInfoToGoogleScript
      google.script.run.addInfo(titel, autor, auflage);

      //clearInputFields
      document.getElementById("titel").value = "";
      document.getElementById("autor").value = "";
      document.getElementById("auflage").value = "";
    }


    //Table JS
    document.addEventListener("DOMContentLoaded", function(){
        google.script.run.withSuccessHandler(addElementsToTable).getTableData();
      });

      function addElementsToTable(data){
        var tbody = document.getElementById("table-body");

        data.forEach(function(r){
          var row = document.createElement("tr");
          var col1 = document.createElement("td");
          col1.textContent = r[0];
          var col2 = document.createElement("td");
          col2.textContent = r[1];
          var col3 = document.createElement("td");
          col3.textContent = r[2];
          var col4 = document.createElement("td");


          if(r[3]=="nicht verfügbar"){
            console.log("nicht verfügbar erkannt");
            col4.textContent = r[3] + " | Klick zum Zurückgeben";
            col4.setAttribute("style", "background-color: #E40046;color: #ffffff");
          }

          else{
           console.log("verfügbar erkannt");
           var link = document.createElement("a");
           link.setAttribute("onclick", "test(r[0],r[1],r[2])");
           link.textContent = r[3] + " | Klick zum Ausleihen";
           link.setAttribute("style", "color: #ffffff;");
           col4.setAttribute("style", "background-color: #00965E;");
           col4.appendChild(link);
          }

          row.appendChild(col1);
          row.appendChild(col2);
          row.appendChild(col3);
          row.appendChild(col4);
          tbody.appendChild(row);

         });
      }

    function test(titel,autor,auflage) {
        console.log("Test");
        console.log("Titel: " + titel + " | Autor: " + autor + " | Auflage: " + auflage);
      }
    </script>
  </body>
</html>

错误信息: "Uncaught ReferenceError: r is not defined at HTMLAnchorElement.onclick"

【问题讨论】:

    标签: javascript html foreach onclick


    【解决方案1】:

    不要在现代程序中使用onxyz 属性进行事件处理。他们创建的函数是在全局范围内创建的。您的 r 变量是函数调用的本地变量。

    改为使用现代事件处理:

    link.addEventListener("click", function() {
        test(r[0], r[1], r[2]);
    });
    

    当点击发生时,将调用 test 并使用 r 中的当前值。事件处理程序关闭 r

    现场示例:

    var fakeData = [
        [
            "first row value 0",
            "first row value 1",
            "first row value 2",
            "first row value 3"
        ],
        [
            "second row value 0",
            "second row value 1",
            "second row value 2",
            "nicht verfügbar"
        ],
        [
            "third row value 0",
            "third row value 1",
            "third row value 2",
            "third row value 3"
        ]
    ];
    
    function test(x, y, z) {
        console.log(x, y, z);
    }
    
    var tbody = document.getElementById("the-body");
    
    fakeData.forEach(function(r) {
        var row = document.createElement("tr");
        var col1 = document.createElement("td");
        col1.textContent = r[0];
        var col2 = document.createElement("td");
        col2.textContent = r[1];
        var col3 = document.createElement("td");
        col3.textContent = r[2];
        var col4 = document.createElement("td");
    
        if(r[3]=="nicht verfügbar"){
            console.log("nicht verfügbar erkannt");
            col4.textContent = r[3] + " | Klick zum Zurückgeben";
            col4.setAttribute("style", "background-color: #E40046;color: #ffffff");
        }
    
        else{
            console.log("verfügbar erkannt");
            var link = document.createElement("a");
            link.addEventListener("click", function() {
                test(r[0], r[1], r[2]);
            });
            link.textContent = r[3] + " | Klick zum Ausleihen";
            link.setAttribute("style", "color: #ffffff;");
            col4.setAttribute("style", "background-color: #00965E;");
            col4.appendChild(link);
        }
    
        row.appendChild(col1);
        row.appendChild(col2);
        row.appendChild(col3);
        row.appendChild(col4);
        tbody.appendChild(row);
    
    });
    
    // Subsequent change to the underlying data
    fakeData.forEach(function(r) {
        r[0] += " - updated";
        r[1] += " - updated";
        r[2] += " - updated";
    });
    &lt;table&gt;&lt;tbody id="the-body"&gt;&lt;/tbody&gt;&lt;/table&gt;

    请注意,当您单击时,它会看到r[0] 等的更新值。


    如果您希望函数使用 r 中的值的 当前 值(在创建函数时,而不是在单击时),您可以使用 bind

    link.addEventListener("click", test.bind(null, r[0], r[1], r[2]));
    

    这会获取您创建函数时的值。

    现场示例:

    var fakeData = [
        [
            "first row value 0",
            "first row value 1",
            "first row value 2",
            "first row value 3"
        ],
        [
            "second row value 0",
            "second row value 1",
            "second row value 2",
            "nicht verfügbar"
        ],
        [
            "third row value 0",
            "third row value 1",
            "third row value 2",
            "third row value 3"
        ]
    ];
    
    function test(x, y, z) {
        console.log(x, y, z);
    }
    
    var tbody = document.getElementById("the-body");
    
    fakeData.forEach(function(r) {
        var row = document.createElement("tr");
        var col1 = document.createElement("td");
        col1.textContent = r[0];
        var col2 = document.createElement("td");
        col2.textContent = r[1];
        var col3 = document.createElement("td");
        col3.textContent = r[2];
        var col4 = document.createElement("td");
    
        if(r[3]=="nicht verfügbar"){
            console.log("nicht verfügbar erkannt");
            col4.textContent = r[3] + " | Klick zum Zurückgeben";
            col4.setAttribute("style", "background-color: #E40046;color: #ffffff");
        }
    
        else{
            console.log("verfügbar erkannt");
            var link = document.createElement("a");
            link.addEventListener("click", test.bind(null, r[0], r[1], r[2]));
            link.textContent = r[3] + " | Klick zum Ausleihen";
            link.setAttribute("style", "color: #ffffff;");
            col4.setAttribute("style", "background-color: #00965E;");
            col4.appendChild(link);
        }
    
        row.appendChild(col1);
        row.appendChild(col2);
        row.appendChild(col3);
        row.appendChild(col4);
        tbody.appendChild(row);
    
    });
    
    // Subsequent change to the underlying data
    fakeData.forEach(function(r) {
        r[0] += " - updated";
        r[1] += " - updated";
        r[2] += " - updated";
    });
    &lt;table&gt;&lt;tbody id="the-body"&gt;&lt;/tbody&gt;&lt;/table&gt;

    请注意,当您单击时,它会看到 r[0] 等的值,就像创建单击处理程序时一样。

    怀疑你想要后者(bind),但两者都有用例。


    旁注:您可以直接使用其反射属性,而不是设置style 属性。例如,这个:

    col4.setAttribute("style", "background-color: #E40046;color: #ffffff");
    

    完全替换元素上的内联样式(例如,删除之前存在的任何样式)。如果你想要,那就太好了;否则,您可以这样做:

    col4.style["background-color"] = "#E40046"; // Notice the [""] syntax
    col4.style.color = "#ffffff";
    

    col4.style.backgroundColor = "#E40046"; // Notice no "-" and a capital C
    col4.style.color = "#ffffff";
    

    【讨论】:

    • 谢谢。你的建议对我帮助很大!
    猜你喜欢
    • 1970-01-01
    • 2016-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-01
    • 2012-04-26
    相关资源
    最近更新 更多