[英]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.