Javascript:如何在提交表单之前使用异步值填充文本字段?

发布于 2025-01-14 04:48:06 字数 1589 浏览 2 评论 0 原文

我想从客户端向以太坊区块链提交交易,获取交易哈希,然后将该哈希提交到我的后端。

在前端,我有一个这样的表单:

<form id="formConfirm" method="POST" action="/step2" onSubmit="processStep1">
  <input id="textWalletAddress" name="walletAddress" type="text" readonly />
  <input id="textEncodedFunctionCall" th:value="${encodedFunctionCall}" readonly />
  <input type="text" id="textTxHash" readonly />
  <input type="submit" value="Submit" />
</form>

在函数内部,我想提交交易,获取相应的哈希值,并用它填充一个字段,以便我可以将其推送到后端。

async function processStep1(e) {
  // edit1: trying out preventDefault
  alert('Before preventDefault');
  e.preventDefault();
  alert('After preventDefault');

  let efc = document.getElementById('textEncodedFunctionCall').value;
  let walletAddress = document.getElementById('textWalletAddress').value;
  const txParams = {
    to: CONTRACT,
    from: walletAddress,
    'data': efc
  };
  
  if (window.ethereum) {
    try {
      const txHash = await window.ethereum.request({
        method: "eth_sendTransaction",
        params: [txParams]
      });
      document.getElementById('textTxHash').value = txHash;
      // how/where do I preventDefault()?
    } catch (err) {
      alert('ERROR! ' + err);
    }
  } else {
    alert('MetaMask is not installed!');
  }
}

我遇到的问题是表单在没有哈希的情况下继续提交。交易确实完成了(有 MetaMask 提示等),但在我的后端我收到错误。

我读到我应该 preventDefault() 但我不知道如何应用它。有人可以指导我如何做到这一点吗?纯 JavaScript 将是最理想的,因为我试图减少对外部库的依赖。


Edit1:我一开始就尝试过 preventDefault 但我什至没有看到任何警报。

Edit2:添加了我的问题中缺少的字段

I want to submit a transaction from the client to Ethereum blockchain, get back a transaction hash, and then submit this hash to my backend.

On the front-end I have a form like this:

<form id="formConfirm" method="POST" action="/step2" onSubmit="processStep1">
  <input id="textWalletAddress" name="walletAddress" type="text" readonly />
  <input id="textEncodedFunctionCall" th:value="${encodedFunctionCall}" readonly />
  <input type="text" id="textTxHash" readonly />
  <input type="submit" value="Submit" />
</form>

Inside the function, I want to submit the transaction, get back the corresponding hash, and populate a field with it so that I can push it to my backend.

async function processStep1(e) {
  // edit1: trying out preventDefault
  alert('Before preventDefault');
  e.preventDefault();
  alert('After preventDefault');

  let efc = document.getElementById('textEncodedFunctionCall').value;
  let walletAddress = document.getElementById('textWalletAddress').value;
  const txParams = {
    to: CONTRACT,
    from: walletAddress,
    'data': efc
  };
  
  if (window.ethereum) {
    try {
      const txHash = await window.ethereum.request({
        method: "eth_sendTransaction",
        params: [txParams]
      });
      document.getElementById('textTxHash').value = txHash;
      // how/where do I preventDefault()?
    } catch (err) {
      alert('ERROR! ' + err);
    }
  } else {
    alert('MetaMask is not installed!');
  }
}

The problem I encounter is that the form goes ahead with the submission without the hash. The transaction does go through (with MetaMask prompts and all) but on my backend I get an error.

I read that I am supposed to preventDefault() but I am not sure how to apply it. Can someone guide me on how to do this? Plain JavaScript would be the most ideal as I am trying to reduce dependencies on external libraries.


Edit1: I tried preventDefault at the beginning but I don't even see any alerts.

Edit2: Added the fields that were missing in my question

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

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

发布评论

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

评论(3

尸血腥色 2025-01-21 04:48:06

好吧,我会选择:

  1. 删除 onSubmit="processStep1()" 并将其替换为 javascript:document.getElementById('formConfirm').onsubmit = processStep1;。请注意这里缺少 ()!编辑:正如有人已经指出的那样,在 onSubmit="processStep1()" 中删除 () 也应该可以解决问题
  2. 然后,您的函数获取一个事件作为参数,您可以执行异步函数processStep1(event) { ... }
  3. 现在最后一件事是在开头的某个地方调用 event.preventDefault() 。请记住,您正在阻止默认操作,因此您不会提交表单 - 您可能想要使用 fetch() 手动提交表单。

除此之外,您可以将 input type="submit" 替换为具有单击功能的自定义按钮,这样您就不必调用 event.preventDefault()。但在我看来没有太大区别。

Well I'd go with:

  1. Removing onSubmit="processStep1()" and replacing it with javascript: document.getElementById('formConfirm').onsubmit = processStep1;. Note the lack of () here! EDIT: as someone already pointed out, removing () in onSubmit="processStep1()" should also do the trick
  2. Then, your function gets an event as parameter, co you can do async function processStep1(event) { ... }
  3. Now the last thing is to call event.preventDefault() somewhere at the beginning. Remember that you are preventing default action, so you are not submitting the form - you probably want to use fetch() to submit the form manually.

Other than that you can replace input type="submit" with a custom button with your function on click, so you don't have to call event.preventDefault(). But imo no big difference.

惟欲睡 2025-01-21 04:48:06

一些错误:

  1. onSubmit 采用函数而不是函数调用,因此应该是:
<form ... onSubmit="processStep1"> ...
  1. 如果您想停止表单操作,则需要调用事件的 preventDefault 方法,这会阻止浏览器首先联系表单操作:
async function processStep1(event) {
   // I suggest as first row so you are sure
   // the form will stop before any other operation/error
   // made by this function
   event.preventDefault();
   ...
  1. 然后您需要使用 XHR (XMLHttpRequest - MDN) 因为您停止了浏览器本应执行的正常调用(通过阻止事件的默认设置):
function sendForm(form) {
   var formData = new FormData();
   var inputs = form.querySelectorAll('input');

   inputs.forEach(function(input) {
      var data;
      // simplified version for files (since it seems you don't need it)
      if (input.type === 'file') { data = input.files[0]; }
      else { data = input.value; }
      formData.append(input.name, data);
   });

   return new Promise(function(y, n) {
      var xhr= new XMLHttpRequest();
      xhr.onreadystatechange = function () {
          if (xhr.readyState === XMLHttpRequest.DONE) {
             if (status === 0 || (status >= 200 && status < 400)) { 
                y(xhr.responseText);
          }
          else { n(xhr); }
      };
      xhr.open(form.method, form.action);
      xhr.send(formData);
   });
}

async function processStep1(event) {
   ...
   // at the end of your function
   try {
     var response = await sendForm(this);
     // threat response
   } catch(ex) {
     /// threat exceptions
   }
}

有关更多信息FormData 对象 (MDN) 我建议您点击链接以获得更好的阅读效果。

Some errors:

  1. onSubmit takes a function and not a function call so it should be:
<form ... onSubmit="processStep1"> ...
  1. If you want to stop the form action you need to call the preventDefault method of the event, which stops the browser to contacting the form action at first place:
async function processStep1(event) {
   // I suggest as first row so you are sure
   // the form will stop before any other operation/error
   // made by this function
   event.preventDefault();
   ...
  1. You then need to call your backend with a XHR (XMLHttpRequest - MDN) because you stopped the normal call that your browser would have done (by preventing the default of the event):
function sendForm(form) {
   var formData = new FormData();
   var inputs = form.querySelectorAll('input');

   inputs.forEach(function(input) {
      var data;
      // simplified version for files (since it seems you don't need it)
      if (input.type === 'file') { data = input.files[0]; }
      else { data = input.value; }
      formData.append(input.name, data);
   });

   return new Promise(function(y, n) {
      var xhr= new XMLHttpRequest();
      xhr.onreadystatechange = function () {
          if (xhr.readyState === XMLHttpRequest.DONE) {
             if (status === 0 || (status >= 200 && status < 400)) { 
                y(xhr.responseText);
          }
          else { n(xhr); }
      };
      xhr.open(form.method, form.action);
      xhr.send(formData);
   });
}

async function processStep1(event) {
   ...
   // at the end of your function
   try {
     var response = await sendForm(this);
     // threat response
   } catch(ex) {
     /// threat exceptions
   }
}

For more info on FormData Object (MDN) I suggest you to follow the link for a better reading.

咋地 2025-01-21 04:48:06

这里。我只是把整个代码贴出来。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <form id="formConfirm">
      <input id="textWalletAddress" name="walletAddress" type="text" />
      <input id="textEncodedFunctionCall" th:value="${encodedFunctionCall}" />
      <input type="text" id="textTxHash" readonly />
      <input type="submit" value="Submit" />
    </form>

    <script>
      const form = document.getElementById("formConfirm")

      async function processStep1(e) {
        // let efc = document.getElementById("textEncodedFunctionCall").value
        // let walletAddress = document.getElementById("textWalletAddress").value
        // const txParams = {
        //   to: CONTRACT,
        //   from: walletAddress,
        //   data: efc,
        // }

        // if (window.ethereum) {
        //   try {
        //     const txHash = await window.ethereum.request({
        //       method: "eth_sendTransaction",
        //       params: [txParams],
        //     })

        //     document.getElementById("textTxHash").value = txHash
        //     // how/where do I preventDefault()?
        //   } catch (err) {
        //     alert("ERROR! " + err)
        //   }
        // } else {
        //   alert("MetaMask is not installed!")
        // }
        document.getElementById("textTxHash").value = "HASH"
      }

      form.addEventListener("submit", async function (e) {
        e.preventDefault()

        await processStep1()
      })
    </script>
  </body>
</html>

Here. I just put the whole code.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <form id="formConfirm">
      <input id="textWalletAddress" name="walletAddress" type="text" />
      <input id="textEncodedFunctionCall" th:value="${encodedFunctionCall}" />
      <input type="text" id="textTxHash" readonly />
      <input type="submit" value="Submit" />
    </form>

    <script>
      const form = document.getElementById("formConfirm")

      async function processStep1(e) {
        // let efc = document.getElementById("textEncodedFunctionCall").value
        // let walletAddress = document.getElementById("textWalletAddress").value
        // const txParams = {
        //   to: CONTRACT,
        //   from: walletAddress,
        //   data: efc,
        // }

        // if (window.ethereum) {
        //   try {
        //     const txHash = await window.ethereum.request({
        //       method: "eth_sendTransaction",
        //       params: [txParams],
        //     })

        //     document.getElementById("textTxHash").value = txHash
        //     // how/where do I preventDefault()?
        //   } catch (err) {
        //     alert("ERROR! " + err)
        //   }
        // } else {
        //   alert("MetaMask is not installed!")
        // }
        document.getElementById("textTxHash").value = "HASH"
      }

      form.addEventListener("submit", async function (e) {
        e.preventDefault()

        await processStep1()
      })
    </script>
  </body>
</html>

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