![[Tistory] 게시글 쓰기 완료 - 전체코드](https://image.inblog.dev?url=https%3A%2F%2Finblog.ai%2Fapi%2Fog%3Ftitle%3D%255BTistory%255D%2520%25EA%25B2%258C%25EC%258B%259C%25EA%25B8%2580%2520%25EC%2593%25B0%25EA%25B8%25B0%2520%25EC%2599%2584%25EB%25A3%258C%2520-%2520%25EC%25A0%2584%25EC%25B2%25B4%25EC%25BD%2594%25EB%2593%259C%26logoUrl%3Dhttps%253A%252F%252Finblog.ai%252Finblog_logo.png%26blogTitle%3DCoding_study&w=2048&q=75)
1. PostRequest SaveDTO 수정
// 게시글 쓰기
@Data
public static class SaveDTO{
private String title;
private String content;
private Integer categoryId;
private MultipartFile thumbnailFile;
public Post toEntity(User sessionUser, Category category, String content, MultipartFile thumbnailFile){
String imgThumbnailFile = ImageUtil.save(thumbnailFile);
return Post.builder()
.user(sessionUser)
.title(title)
.content(content)
.category(category)
.thumbnailFile(imgThumbnailFile)
.build();
}
}
2. PostService - postSave() 추가
// 게시글 쓰기
@Transactional
public void postSave(Integer sessionUserId, PostRequest.SaveDTO reqDTO){
User sessionUser = userJPARepo.findById(sessionUserId)
.orElseThrow(() -> new Exception404("회원 정보가 존재하지 않습니다."));
Category category = categoryJPARepo.findById(reqDTO.getCategoryId())
.orElseThrow(() -> new Exception404("카테고리가 존재하지 않습니다"));
postJPARepo.save(reqDTO.toEntity(sessionUser, category, reqDTO.getContent(), reqDTO.getThumbnailFile()));
}
3. PostController
// 게시글 쓰기
@PostMapping("/s/post/save")
public String save(@ModelAttribute PostRequest.SaveDTO reqDTO){
System.out.println("Post SaveDTO"+ reqDTO);
User user = (User) session.getAttribute("sessionUser");
postService.postSave(user.getId(), reqDTO);
return "redirect:/post/list";
}
4. post - WriteForm.mustache
{{>/layout/main-header}}
<style>
.ql-editor {
min-height: 40vh;
}
</style>
<div class="container">
<form id="postWriteForm" onsubmit="return getQuill()">
<!-- <form id="postWriteForm" onsubmit="return getQuill()">-->
<div class="form-group">
<select class="form-control" id="categoryId" name="categoryId">
{{#model.categoryNameDTO}}
<option value="{{id}}">{{categoryName}}</option>
{{/model.categoryNameDTO}}
</select>
</div>
<input id="title" type="text" name="title" class="form-control" placeholder="Enter Title">
<!-- 퀼 에디터 디자인 부분-->
<div id="toolbar-container">
<span class="ql-formats">
<select class="ql-font"></select>
<select class="ql-size"></select>
</span>
<span class="ql-formats">
<button class="ql-bold"></button>
<button class="ql-italic"></button>
<button class="ql-underline"></button>
<button class="ql-strike"></button>
</span>
<span class="ql-formats">
<select class="ql-color"></select>
<select class="ql-background"></select>
</span>
<span class="ql-formats">
<button class="ql-script" value="sub"></button>
<button class="ql-script" value="super"></button>
</span>
<span class="ql-formats">
<button class="ql-header" value="1"></button>
<button class="ql-header" value="2"></button>
<button class="ql-blockquote"></button>
</span>
<span class="ql-formats">
<button class="ql-list" value="ordered"></button>
<button class="ql-list" value="bullet"></button>
<button class="ql-indent" value="-1"></button>
<button class="ql-indent" value="+1"></button>
</span>
<span class="ql-formats">
<button class="ql-direction" value="rtl"></button>
<select class="ql-align"></select>
</span>
<span class="ql-formats">
<button class="ql-link"></button>
<button class="ql-image"></button>
<button class="ql-video"></button>
</span>
<span class="ql-formats">
<button class="ql-clean"></button>
</span>
</div>
<!-- 퀼 에디터 디자인 부분-->
<!--내용적는 부분-->
<div id="editor-container"></div>
<div class="form-control d-flex justify-content-end">
<div>섬네일 사진 등록 : <input id="thumbnailFile" type="file" name="thumbnailFile"></div>
</div>
<button type="submit" class="my_active_btn">글쓰기 등록</button>
</form>
<br/>
</div>
<script>
// Quill 에디터의 설정 부분
var quill = new Quill('#editor-container', {
modules: {
formula: true,
syntax: true,
toolbar: '#toolbar-container'
},
placeholder: '게시물을 작성해주세요.',
theme: 'snow'
});
// Quill 에디터의 설정 부분
// 카테고리가 없으면 alret창 뜨게
let noCategory = {{noCategory}};
console.log("noCategory: ", noCategory); // 값 확인용 로그
if (noCategory) {
swal.fire({
text: "카테고리를 먼저 등록해주세요",
icon: "warning",
button: "확인"
}).then(() => {
window.location.href = "/s/category/write-form"; // 카테고리 생성 페이지로 리다이렉트
});
}
// 카테고리가 없으면 alret창 뜨게
// 게시글 쓰기
$("#postWriteForm").on("submit", function(e) {
e.preventDefault(); // 폼이 바로 제출되지 않도록 함
// 제목 값 읽기
let title = $("#title").val();
console.log("제목: " + title);
// 카테고리 아이디 값 읽기
let categoryId = $("#categoryId").val();
console.log("categoryId: " + categoryId);
// Quill 에디터 내용 읽기
let quillContent = quill.root.innerHTML;
console.log("Quill Content: " + quillContent); // HTML 태그와 함께 텍스트 출력 (글꼴, 색상 등 유지)
// 폼 데이터 생성 (파일 및 텍스트 데이터 포함)
let formData = new FormData(this); // 현재 폼의 데이터를 가져옴
formData.append("content", quillContent); // Quill 에디터의 내용을 추가
$.ajax({
url: "/s/post/save",
data: formData,
contentType: false, // 기본적으로 jQuery는 데이터를 문자열로 처리하지만, 파일 전송을 위해 false로 설정
processData: false, // FormData를 사용할 때는 multipart/form-data를 사용하므로 false로 설정
type: 'POST'
}).done((res) => {
Swal.fire({
text: "게시글 등록이 완료되었습니다.",
icon: "success",
button: "확인"
}).then(() => {
window.location.href = "/post/list";
});
}).fail((res) => {
Swal.fire({
text: "게시글 등록 실패",
icon: "warning",
button: "확인"
});
});
});
</script>
{{>/layout/footer}}
5. 화면 확인

Share article