我正在开发Spring Boot应用程序。我有一个收藏夹按钮,其中按钮图像根据用户是否收藏该项目而改变。
最初,我通过接受表单发布请求,更新数据库并将重定向发送回Referer来使其工作,但这每次都会重新加载页面,所以我想我会尝试使用jQuery Ajax。
Controller.java:
// //Favorite/Unfavorite existing recipes
// @RequestMapping(value = "/recipes/{id}/favorite", method = RequestMethod.POST)
// public String favoriteRecipe(@PathVariable Long id, Model model, HttpServletRequest request, Authentication
// authentication) {
//
// User user = userService.findByUsername(authentication.getName());
// model.addAttribute("user", user);
// Recipe recipe = recipeService.findById(id);
//
// userService.toggleFavorite(user, recipe);
//
// userService.save(user);
//
// return "redirect:" + request.getHeader("Referer");
// }
// Favorite/Unfavorite existing recipes
@PostMapping("/recipes/{id}/favorite")
@ResponseStatus(value = HttpStatus.OK)
public void favoriteRecipe(@PathVariable("id") Long id, Model model, Authentication authentication) {
User user = userService.findByUsername(authentication.getName());
//model.addAttribute("user", user);
Recipe recipe = recipeService.findById(id);
userService.toggleFavorite(user, recipe);
userService.save(user);
//return new ResponseEntity<>(HttpStatus.OK);
}
index.html:
<a th:href="@{|/details/${recipe.id}|}">
<div class="grid-70">
<p>
<form id="test" th:action="@{|/recipes/${recipe.id}/favorite|}" method="post" style="display:inline">
<button type="submit" id="favorite-button-index">
<img th:src="${recipe.userFavorites.contains(#authentication.name)} ? @{/assets/images/favorited.svg} : @{/assets/images/favorite.svg}"
style="height: 12px;">
</button>
</form>
<span th:text="${recipe.name}"> </span>
</p>
</div>
</a>
app.js:
$('#test').submit(function (e) {
e.preventDefault()
$('#favorite-button-detail').submit(function (e) {
e.preventDefault()
var recipeID = [[${recipe.id}]];
var url = "/recipes/" + recipeID + "/favorite";
$.post(url, function(data) {
alert(data)
});
})
})
这是我尝试在app.js中实现的方式。我已经确认数据库中的数据正在更新,但是我无法停止重定向到POST URL。问题似乎来自表单中的th:action。
我已经查看了很多其他问题/示例,但无法弄清楚为什么会发生这种情况。我尝试了preventdefault,返回false,包装在$(document).ready()中。
任何帮助将不胜感激。谢谢!
答案 0 :(得分:1)
有两个嵌套的提交不是很好。而且我不确定将[[${recipe.id}]]
包裹在双数组中的想法是什么... ??
尝试:
$('#test').on("submit", function (e) {
e.preventDefault();
$.post(this.action, function(data) {
console.log(data);
});
});
其中this.action
是实际表单的 action 属性值@{|/recipes/${recipe.id}/favorite|}
而且您不再需要任何按钮JS东西。
答案 1 :(得分:0)
除了Roko's答案之外,您还必须找到一种解决方案来刷新ui,以便在不刷新整个页面的情况下更改按钮图像,因为您使用的是服务器端渲染模板引擎。 我建议您在这样的成功响应后只更改按钮的图像:
$('#test').on("submit", function (e) {
e.preventDefault();
$.post(this.action, function(data) {
console.log(data);
var imageUrl = (data.favorited)?'/assets/images/favorited.svg':'/assets/images/favorite.svg';
$('#favorite-button-index>img').attr('src', imageUrl);
});
};
在这种情况下,也要使data.favorited
工作,您应该从spring控制器方法返回有关用户是否喜欢的数据。这是一个返回json数据的示例,因此您可以轻松地在javascript中使用
@PostMapping("/recipes/{id}/favorite")
@ResponseBody
public Map<String, Object> favoriteRecipe(@PathVariable("id") Long id, Authentication authentication) {
User user = userService.findByUsername(authentication.getName());
Recipe recipe = recipeService.findById(id);
userService.toggleFavorite(user, recipe);
userService.save(user);
boolean hasFavorite = recipe.userFavorites.contains(authentication.getName());
Map<String, Object> resultJson = new HashMap<>();
resultJson.put("favorited", hasFavorite);
return resultJson;
}