강의

멘토링

커뮤니티

인프런 커뮤니티 질문&답변

이재영님의 프로필 이미지
이재영

작성한 질문수

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

상품 수정하는 부분 질문드립니다.

작성

·

467

0

현재 타임리프를 자바스크립트로 바꿔서 진행하고 있습니다. 

등록한 상품들을 출력하는 부분까지는 fetch를 통해 해결을 했는데요.

상품 수정하는 부분부터는 url에 아이템id가 유동적으로 들어가다 보니까 프론트쪽에서 url에 아이템id값을 어떻게 받아야 할지 모르겠습니다.

@GetMapping(value = "/items/{itemId}/edit")  

@PostMapping(value = "/items/{itemId}/edit") <--- 컨트롤러 부분

fetch("/items/{itemId}/edit", {     <--- 프론트 부분
method: "POST",
headers: {
"Content-Type": "application/json",
},

다른 해결방법이 있는지 궁금합니다.

답변 4

0

심플하게 비동기 처리 하는 코드 구현해봤습니다.

동작에 대해 설명드리면, 버튼을 클릭할 때 마다 itemId를 넘겨서 서버에서 json 객체를 가져오는 동작을 합니다. 

추가적인 기능 구현과 로직은 참맛님께서 직접 구현해보시길 바랍니다.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button id="btn">버튼</button>
<script>
let btn = document.getElementById("btn");
let itemId = 2;

btn.addEventListener('click', function func(){
fetch(`/item/${itemId}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
}
})
.then(res => res.json())
.then(data => {
console.log(data);
});
});
</script>
</body>
</html>
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor @NoArgsConstructor
public class Item {
private Integer itemId;
private String name;

}

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
@PostMapping("/item/{itemId}")
public Item updateItem(@PathVariable Long itemId) {
Item item1 = new Item(1, "아이템1");
Item item2 = new Item(2, "아이템2");

if (itemId == 1) {
item1.setName("상품1");
} else {
item2.setName("상품2");
}
return itemId == 1? item1 : item2;
}

}

0

JS의 fetch에 첫번째 인자로 full path 를 작성해보시겠어요?

로컬에서 개발 중이시라면

http://localhost:8080/~ 

그리고 @PostMapping 의 return 은 JSON을 반환하셔야 합니다.

그래야 fetch 'then'에서 json을 받아올 수 있습니다.

이재영님의 프로필 이미지
이재영
질문자

여전히 똑같은 오류가 발생합니다..

추가로 @postmapping 대신에 

@requestmapping(value = "/items/", method=@RequestMethod.POST, produces="application/json") 로 해도 안되네요.

@PostMapping(value = "/items/{itemId}")
public BeverageForm updateItem(@PathVariable Long itemId, @RequestBody BeverageForm beverageForm) {
if (itemService.findOne(itemId).getCategory().equals("beverage")) {
itemService.updateBeverage(beverageForm.getId(), beverageForm.getName(), beverageForm.getPrice(), beverageForm.getSize());
}
return beverageForm;
}

function updateB() {
let url = window.location.pathname;
let itemId = url.split('/');
console.log("updateB");
console.log(itemId[2]);
let beverageName = document.getElementById("updateBName").value;
let beveragePrice = document.getElementById("updateBPrice").value;
let beverageSize = document.getElementById("updateBSize").value;

fetch(`http://localhost:8080/items/${itemId[2]}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
name: beverageName,
price: beveragePrice,
size: beverageSize,
}),
})
.then((response) => response.json())
.then((form) => console.log(form));
}

0

아 참맛님 제가 질문을 잘못 이해했었네요. 죄송합니다.

fetch(`/items/${itemId}/edit`,

작성하신 방법은 미리 선언되어 있는 itemId를 요청 url에 유동적으로 포함시키기 위해서 template literal을 사용한 코드인 것이고, 

아래와 같이 하는게 맞는 것 같네요.

const update = (itemId) => {
fetch(`/items/${itemId}/edit`,{
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
}
})
.then(res => res.json())
.then(item=> {
const updateItemId = item.id;
})};

가령 위의 요청을 보냈을 때 서버에서 다음과 같이 처리한다고 하자면,


@PostMapping("/items/{itemId}/edit")
@ResponseBody
public Item update(@PathVariable("itemId") Long itemId) {
Item updateItem = itemRepository.findVById(itemId);
updateItem.update();

return updateItem;
}

update된 아이템 json객체를 반환하도록 합니다.

세부 로직은 조금씩 달라질 수 있겠지만 이런 흐름으로 하시면 되지 않나 싶습니다.

이재영님의 프로필 이미지
이재영
질문자

답변 감사합니다. itemId는 잘 연결됐습니다. 

하지만 상품을 수정하고 submit을 누르면 아래와 같은 오류가 뜹니다.

There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'POST' not supported
org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
상품을 등록할때와 같은 로직을 사용해서 오류가 발생하는 건지 검색을 해도 이유를 모르겠습니다.
또한 저는 put방식을 쓰고 싶은데 putmapping으로 바꿀 경우에도 위와 똑같은 post오류가 발생합니다.
도움주시면 감사하겠습니다.
@PostMapping(value = "/items/{itemId}")
public String updateItem(@PathVariable Long itemId, @RequestBody BeverageForm beverageForm, @RequestBody FoodForm foodForm) {
if (itemService.findOne(itemId).getCategory().equals("beverage")) {
itemService.updateBeverage(beverageForm.getId(), beverageForm.getName(), beverageForm.getPrice(), beverageForm.getSize());
} else {
itemService.updateFood(foodForm.getId(), foodForm.getName(), foodForm.getPrice(), foodForm.getGram());
}
return "/items/itemList";
}
function updateB() {
let url = window.location.pathname;
let itemId = url.split('/');
console.log("updateB");
console.log(itemId[2]);
let beverageName = document.getElementById("updateBName").value;
let beveragePrice = document.getElementById("updateBPrice").value;
let beverageSize = document.getElementById("updateBSize").value;

fetch(`/items/${itemId[2]}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
name: beverageName,
price: beveragePrice,
size: beverageSize,
}),
})
.then((response) => response.json())
.then((form) => console.log(form));
}

0

안녕하세요. 참맛님, 공식 서포터즈 OMG입니다.

자바스크립트의 template literal을 이용하면 되는데요,

사용 예시는 아래의 링크를 참고해주세요

https://stackoverflow.com/questions/50983150/how-to-pass-a-variable-with-url-on-javascript-fetch-method

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Template_literals

감사합니다.

이재영님의 프로필 이미지
이재영
질문자

먼저 답변 감사합니다.

fetch(`/items/${itemId}/edit`,

단순히 이렇게 바꾸니 수정폼에서 수정할 값을 입력한뒤 submit을 하면 아래의 에러가 뜹니다.

콘솔창에 

uncaught referenceerror: itemId is not defined at htmlbuttonelement.onclick 가 잠깐 뜨고

바로 아래화면으로 넘어갑니다.

There was an unexpected error (type=Internal Server Error, status=500).
id to load is required for loading; nested exception is java.lang.IllegalArgumentException: id to load is required for loading
org.springframework.dao.InvalidDataAccessApiUsageException: id to load is required for loading; nested exception is java.lang.IllegalArgumentException: id to load is required for loading at.............................
................ at hanium.smartbell.service.ItemService.updateBeverage(ItemService.java:45) 
id값이 필요하다는 것 같은데 그럼 itemId를 제대로 인식하지 못한 것 아닌가요? 

이재영님의 프로필 이미지
이재영

작성한 질문수

질문하기