簡體   English   中英

在沒有頁面重定向/刷新的情況下觸發 Spring MVC controller 方法

[英]Triggering Spring MVC controller method without page redirect/refresh

我想從 Thymeleaf 視圖觸發 Spring MVC controller 方法,而不從該方法返回任何內容並且不刷新頁面。

我有以下 HTML 頁面:

在此處輸入圖像描述

<!-- 'block item' button code-->
<div class="row">
  <form method="get" th:action="@{'/items/block/' + ${item.itemId}}">
      <button type="submit" class="btn btn-warning">block item</button>
  </form>
</div>

相關的 controller 如下所示:

@GetMapping("/items/block/{itemId}")
@ResponseStatus(value = HttpStatus.OK)
public void blockItem(@PathVariable String itemId) {
    itemService.blockItem(itemId);
}

itemService.blockItem(itemId)調用只是改變了數據庫中相關item object 對應的 boolean 屬性。

目前,每當我通過按塊項目按鈕觸發此方法時,我都會被重定向到 URL ,例如http://localhost:8080/item/block/7C4A3744375523

我不想做任何重定向,而只是執行相關的服務方法邏輯。 我還需要從視圖中刪除相關項目 div,但我可以使用 JavaScript 非常簡單地做到這一點。
我該怎么做? 謝謝。

您的按鈕被定義為type submit

結果,當您單擊它時,表單被提交。

為了防止這種默認行為,您需要做幾件事:主要思想是為您的表單submit事件定義一個處理程序並使用 Javascript 來執行實際的服務器調用。

你可以用不同的方式來做,雖然我認為最好使用事件處理程序來定義所需的行為,並盡可能地將 HTML 代碼與 Javascript 分開。

此外,您似乎正在迭代項目列表。

考慮到這兩件事,請考慮以下代碼片段:

<script>
  // We use the DOMContentLoaded event (https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event)
  // but please, register the form event as you consider appropriate
  document.addEventListener('DOMContentLoaded', () => {
    // Register form submit event handler for every form in your page
    const forms = document.querySelectorAll('form');
    if (forms) {
      forms.forEach(f => {
        let action = f.action;
        f.addEventListener('submit', (event) => {
          // prevent default behavior, i.e., form submission
          event.preventDefault();
          // perform server side request. you can use several options
          // see https://developers.google.com/web/updates/2015/03/introduction-to-fetch, for instance
          // For example, let's use fetch (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
          fetch(action)
            .then((response) => {
              if (!response.ok) {
                throw new Error('Network response was not ok');
              }
              console.log('Request successfully completed');
            })
            .catch((error) => {
              console.error('There has been a problem while contacting server:',      error);
            });
          });
      });
    }
  });
</script>

實際上,您可以擺脫 forms。 請考慮一種稍微不同的方法。 首先,在迭代您的項目時,生成以下 HTML 塊(如果您願意,可以使用data或任何自定義屬性來存儲當前處理的項目 ID):

<!-- 'block item' button code-->
<div class="row">
  <button type="button" class="btn btn-warning item-button" th:id="${item.itemId}">block item</button>
</div>

現在,以與上述類似的方式,為每個項目按鈕注冊處理程序:

<script th:inline="javascript">
  document.addEventListener('DOMContentLoaded', () => {
    // Register handlers for every button
    const buttons = document.querySelectorAll('.item-button');
    if (buttons) {
      buttons.forEach(b => {
        b.addEventListener('click', (event) => {
          let itemId = b.getAttribute('id');
          let link = /*[[@{/items/block/}]]*/ 'link';
          // Perform server side request
          fetch(link + itemId)
            .then((response) => {
              if (!response.ok) {
                throw new Error('Network response was not ok');
              }
              console.log('Request successfully completed');
            })
            .catch((error) => {
              console.error('There has been a problem while contacting server:', error);
            });
        });
      }
    }
  });
</script>

這不是導致重定向的 Thymeleaf 或 Spring MVC,而是在form標簽中submit按鈕。 您需要覆蓋此按鈕的行為以通過 Ajax 發送表單數據並自己處理響應(基本上 - 忽略它) - 例如使用 jQuery 它可能看起來像:

<!-- 'block item' button code-->
<div class="row">
    <form id="someFormId" method="get" th:action="@{'/items/block/' + ${item.itemId}}">
        <button type="submit" class="btn btn-warning">block item</button>
    </form>
</div>

//...

$('#someFormId').submit(function(e) {
    e.preventDefault();
    $.ajax({
        type: 'GET',
        url: '@{'/items/block/' + ${item.itemId}}',
        data: $(this).serialize(),
        // here you can define some actions for beforeSend, success, etc...
        // for example to just ignore:
        success: function(){}
    });
})

有很多想法可以解決這個問題。 請閱讀例如

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM