글쓰기 버튼 만들어주고 글쓰기 화면 만들건데 퀼 에디터 써보자.
글쓰기 화면에서는 드로우바가 필요 없으니까 main-header 사용할 것이다.
여기에 링크 추가해주자.
<!-- Include stylesheet -->
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
글쓰기 화면 mustache를 만들어서 메인 스크립트를 넣어준다.
{{>/layout/main-header}}
<style>
.ql-editor {
min-height: 40vh;
}
</style>
<div class="container">
<form action="/s/post" method="post" enctype="multipart/form-data" onsubmit="return getQuill()">
<input type="text" placeholder="Enter Title" name="title" class="form-control">
<!-- 툴 설정 -->
<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>
<textarea name="content" id="content" class="my_hidden">
</textarea>
<div class="form-control d-flex justify-content-end">
<div>섬네일 사진 등록 : <input type="file" name="thumnailFile"></div>
</div>
<button type="submit" class="my_active_btn">글쓰기 등록</button>
</form>
<br />
</div>
<script>
function getQuill() {
let quillContent = $("#editor-container .ql-editor").html();
$("#content").html(quillContent);
return true;
}
</script>
<!-- Include the Quill library -->
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
<script>
var quill = new Quill('#editor-container', {
modules: {
formula: true,
syntax: true,
toolbar: '#toolbar-container'
},
placeholder: '게시물을 작성해주세요.',
theme: 'snow'
});
</script>
{{>/layout/footer}}
글쓰기 화면으로 이동하는 컨트롤러 생성해주면 된다.
/s가 붙었기 때문에 시큐리티가 알아서 인증 체크를 해준다.
코드가 깔끔해진다.
시큐리티를 사용하지 않으면 인터셉터를 사용하면 된다!!
@GetMapping("/s/post/write-form")
public String writeForm() {
return "/post/writeForm";
}
여러 가지 타입을 전송할 때 multipart/form-data 타입을 사용한다.
Dto를 만들어서 파일을 잘 받았는지 확인해보자.
우리는 name="thumnail"로 이미지를 받았는데 이 파일은 하드디스크에 저장하고,
DB에는 저장 경로를 저장해야 한다.
이름이 잘못된 것 같으니까 thumnailFile로 이름을 바꿔주자.
Valid 체크해줄 건데 title에만 걸어주면 되겠다.
content와 썸네일은 null이 허용이기 때문이다.
하지만 @NotNull은 체크해주자.
공백이 들어와도 되긴 하지만 키 값 자체를 안보내면 안되기 때문이다.
package site.metacoding.blogv3.web.dto.post;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.springframework.web.multipart.MultipartFile;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class PostWriteReqDto {
@NotBlank
@Size(min = 1, max = 60)
private String title;
@NotNull // 공백은 가능한데 키값은 전송하세요
private MultipartFile thumnailFile; // 썸네일은 null 허용
@NotNull // 공백은 가능한데 키값은 전송하세요
private String content; // 컨텐트 null 허용
}
컨트롤러 만들어주자.
성공적으로 데이터를 받으면 해당 유저의 블로그 페이지를 돌려주면 되겠다.
@PostMapping("/s/post")
public String write(PostWriteReqDto postWriteReqDto,
@AuthenticationPrincipal LoginUser loginUser) {
return "redirect:/user/" + loginUser.getUser().getId() + "/post";
}
div 태그로 만들어준 quill 에디터는 내부가 html로 자동 변환된다.
div 태그는 form태그로 전송이 안된다!!
textarea안에는 html이 먹지 않기 때문에 content가 전송되지 않는다.
div 태그의 id가 editor-container인데
이 내부의 내용을 textarea안에 집어넣는 함수를 만들어줄 것이다.
<script>
function getQuill() {
let content = $("#editor-container").html();
console.log(content);
}
</script>
그리고 이 textarea는 보이지 않게 my_hidden 클래스를 걸어주고 name에 content를 달아줘서
얘를 전송해줄 것이다.
잘 담기는지 테스트해보자.
잘 들어온다.
테스트해보면 에디터의 hidden값까지 찾아온다.
이 내부의 ql-editor 클래스의 값을 찾아와야 한다.
css 선택자는 한 칸 띄우면서 내부를 찾아간다.
$("#editor-container .ql-editor").html( );
ql-editor는 클래스니까 .으로 찾아야 한다.
찾은 이 값을 textarea의 html로 넣어주면 끝!
<script>
function getQuill() {
let quillContent = $("#editor-container .ql-editor").html();
$("#content").html(quillContent);
return true;
}
</script>
이렇게 값을 끌어오지 않으면 div의 값이 전송되지 않기 때문에 끌어온 것이다.
디버깅 모드로 확인해보니 잘 들어왔다.
이제 진짜 DB에 넣으면 끝이다.
카테고리 아이디를 잘 받았다.
writeForm을 갈 때 카테고리 데이터를 모델에 담아 가야 한다.
이때 세션 값을 알아야 카테고리를 가져갈 수 있다.
카테고리의 모델을 보면 userId가 있기 때문에 카테고리를 찾을 수 있다.
카테고리의 데이터를 가져오는 것이지 카테고리 서비스가 아니다.
포스트 서비스에서 만들어줘야 한다.
PostService ▼
public List<Category> 게시글쓰기화면(User principal) {
return categoryRepository.findByUserId(principal.getId());
}
PostController ▼
@GetMapping("/s/post/write-form")
public String writeForm(@AuthenticationPrincipal LoginUser loginUser, Model model) {
List<Category> categorys = postService.게시글쓰기화면(loginUser.getUser());
if (categorys.size() == 0) {
throw new CustomException("카테고리 등록이 필요해요");
}
model.addAttribute("categorys", categorys);
return "/post/writeForm";
}
ssar이 가지고 있던 카테고리가 잘 나온다.
카테고리가 없는 유저들은 글을 쓸 수 없게
카테고리 생성 페이지로 redirection 해줘야 한다.
[출처]
https://cafe.naver.com/metacoding
메타 코딩 유튜브
https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9