如何动态调用由客户端交互启动的 servlet 以在 div(不是 iframe)中显示 html 而不会触发页面重新加载

How to dynamically call a servlet initiated by client interaction to display html in div (not iframe) without triggering page reload

我正在为 Web 应用程序编写扩展。它的 API 有一个接口 IFormExtension 需要实现并提供对数据库的访问,并且有一个 String render() 方法,调用该方法以获取将放置的 html在 Web 应用程序的现有 html 中。

我知道在我的问题中提到的不同方面有多个主题,但直到现在我还没有将每个“琐碎”子主题的不同解决方案组合成一个适用于我的“复杂”场景的工作解决方案:

扩展的想法是从数据库中加载和显示列表或 table 中的各种对象,每个条目都带有一个按钮,该按钮会导致额外的 html(项目独有它属于)从 servlet 动态加载以在现有 html 中显示 - 不会触发页面的重新加载。

这是我目前的做法:

// all html I want to pass must be present in the returned String 
// of this method due to the API of the web application and will 
// be placed within a div in the existing html
public String render(..){
   // getting items from database
   String html = "..."; // here the html (see below) is build with values from the items where necessary
   return html;
}

这里是 html 的架构,render() 将 return:

<div>
   <table>
      <tbody>
         <tr>
            <!-- the curly braces expressions are a placeholder for values which will be inserted by the java code above --> 
            <td>
               <form onSubmit="return loadFromServlet({itemId});">
                  <input id="property_{itemid}" type="hidden" value="{itemid.myProperty}">
                  <input type="image" src="{path_to_image}">
               </form>
            </td>
        </tr>      
        <!-- more tr's with different itemId's... -->
      </tbody>
   </table>
</div>
<!-- html from Servlet should show up in this div: -->
<div id="dynamicallyLoadedHtmlHere"/>
<!-- the javascript shows up in the terminal script tag:-->
<script>
    // see the javascript below 
</script>

这里是 javascript:

"use strict";
function loadFromServlet(itemId){
   var xhr = new XMLHttpRequest();
   
   //xhr.addEventListener("load", showDynamicHtml); // I intuitivly wanted to do something like this, but i can't pass a parameter to showDynamicHtml (or at least I don't know how); therefore:
   xhr.open("POST","my/servlet/uri",true);
   var params = "ItemId=" + itemId;
   params += "&MyProperty=" + document.getElementById("property_"+itemId);
   xhr.onload = function (evnt) {
      document.getElementById("dynamicallyLoadedHtmlHere").innerHtml = xhr.responseText;
      evnt.preventDefault();
   } 
   xhr.send(params);
   return false;
}

表单中的图像应该用作提交按钮,它在以前的方法中起作用,当时在我找到 onSubmit 方法之前表单仍然具有 action="my/servlet/uri" method="POST" target="someIFrameId" 属性。我放弃了第一种方法,因为目标应该是 div 而不是 iframe。但是现在函数 loadFromServlet 似乎没有被执行(当我添加 console.log("debug")s 时,控制台中没有显示任何内容并且整个网页刷新 - 即不是预期或预期的行为。我怀疑脚本是否均匀在表格的范围内?

总结:

我希望我已经充分阐述了我的问题。

尝试按照以下方式调整您的 onSubmit 处理程序。

我修改了您的表单以正确调用 loadFromServlet 并且我将 itemId 从函数参数中移出并移到表单的数据属性中,这样我们就可以使用 event loadFromServlet 将有权访问的对象。

我们想要访问事件对象,因此我们可以调用 event.preventDefault() 来阻止页面刷新。

然后JS代码通过访问表单上的data属性获取itemId。

此外,如果您无法让 XHR 为您的请求工作,请尝试 fetch 甚至像 axios 这样的第三方库。

html

<div>
   <table>
      <tbody>
         <tr>
            <!-- the curly braces expressions are a placeholder for values which will be inserted by the java code above --> 
            <td>
               <form onsubmit="loadFromServlet()" data-itemid="{itemId}" data.itemproperty="{itemId.myProperty}">
                  <input type="image" src="{path_to_image}">
               </form>
            </td>
        </tr>      
        <!-- more tr's with different itemId's... -->
      </tbody>
   </table>
</div>
<!-- html from Servlet should show up in this div: -->
<div id="dynamicallyLoadedHtmlHere"/>

js

"use strict";
function loadFromServlet (){
  // Stop the form from submitting (and reloading the page)
  event.preventDefault(); //event is accessible even though it doesn't show up as function parameter
  
  // Get the parameters
  // dataset contains every parameter of a tag prefixed with 'data-'
  const itemId = event.currentTarget.dataset.itemid; 
  const itemProperty = event.currentTarget.dataset.itemproperty;
  
  const URI = 'my/servlet/uri';
  // calling encodeURIComponent() on parameter values to escape potential illegal uri characters
  const params = '?ItemId=' + encodeURIComponent(itemId);
  params += '&myProperty=' + encodeURIComponent(itemProperty);
  
  fetch(URI + params)
  .then(response => response.text())
  .then(data => {
    document.getElementById("dynamicallyLoadedHtmlHere").innerHTML = data;
  });
}

编辑:

我修复了在调试此答案建议的方法时发现的上述代码中的一些错误,并为清楚起见添加了一些注释。