view.pug
댓글 작성, 목록화면 추가
html template 사용하여 한개의 댓글이 표시될 모양을 선언
table
thead
tr
td(colspan='2')
input#content(type="text")
td:button(onclick="writeComment()")
댓글 작성
tbody#commnets
template#comment-template
tr
td.content
td.author
td.createdA
fetch로 api 호출하기
script fucntion writeComment(){ // 댓글 작성 버튼 클릭시 writeComment 실행 const input = document.querySelector('#content') const content = input.value; fetch('/api/posts/#{post.shortId}/comments',{ // input#content에서 내용을 읽어 fetch로 댓글 작성 api 호출 method:'post', header:{'Content-Type':'application/json'}, body:JSON.stringify({content}), }) .then(()=>{ // 호출 결과의 성공 여부를 확인하여, 댓글 불러오기 진행 if(res.ok){ input.value=''; // 댓글 입력칸 초기화 loadComments(); // 댓글 불러오가 } else{ alert('error') } }) }
댓글 작성 api
- 게시글 업데이트 시 $push를 사용하여 comments 배열에 새로 작성된 댓글 추가 > 동시에 들어오는 요청에 대해 정확하게 처리
- api는 render하지 않고 json으로 응답
router.post('/posts/:shortId/commnets',(req,res,next)=>{ const {shortId} = req.params; const {content} = req.body; const author = await User.findOne({shortId:req.user.shortId}) await Post.updateOne({shortId},{ $push:{ //push operator를 사용하여 하나씩 db에 추가함 comments:{ content,author, } } }) res.json({result:'success'}) // api는 render하지 않고 json으로 응답 })
댓글 목록 불러오기
script loadComments(); fucntion loadComments(){ document .querySelector('#commnets') .innerHTML = ''; fetch('/api/posts/#{post.shortId}/comments') .then((res)=>{ if(res.ok){ return res.json() // 받는 데이터 형식은 json으로 통일 } else { throw new Error('error') } }) .then((comments)=>{ comments.forEach(addComment) }); .catch((err)=> alert(err.meesage)) }
댓글 목록 api
- // find에 populate하지 않고 User(model)의 populate를 사용하는 방법도 가능
router.get('/posts/:shortId/commnets',(req,res,next)=>{ const {shortId} = req.params; const post = await Post.findOne({shortId}); await User.populate(post.comments,{ path:'author' }); res.json(post.commnets); })
댓글 화면에 표시
function addComment(comment){ const template = document.querySelector('#comment-template'); const node = document.importNode(template.content,true); node.querySelector('.content').textContent = comment.content node.querySelector('.author').textContent = comment.name node.querySelector('.createdAt').textContent = comment.createdAt document.querySelector('#comments').appendChild(node) }
댓글 스키마
- mongoose의 sub-schema를 이용하여 Post 스키마에 comment를 배열로 추가
- populate를 사용할 때 oid만 저장하는 것과는 다르게 comment의 내용을 게시글이 포함하게 됨.
const CommentSchema = new Schema( { content: String, author: { type: Schema.Types.ObjectId, ref: 'User', }, }, {timestamps: true} ); const PostSchema = new Schema({ comments: [CommentSchema], });