You guessed it, we still need UD.
As with CR, we'll need to add the right routes to our server.js
:
router.route('/comments/:comment_id')
//The put method gives us the chance to update our comment based on the ID passed to the route
.put(function(req, res) {
Comment.findById(req.params.comment_id, function(err, comment) {
if (err)
res.send(err);
//setting the new author and text to whatever was changed. If nothing was changed
// we will not alter the field.
(req.body.author) ? comment.author = req.body.author : null;
(req.body.text) ? comment.text = req.body.text : null;
//save comment
comment.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Comment has been updated' });
});
});
})
//delete method for removing a comment from our database
.delete(function(req, res) {
//selects the comment by its ID, then removes it.
Comment.remove({ _id: req.params.comment_id }, function(err, comment) {
if (err)
res.send(err);
res.json({ message: 'Comment has been deleted' })
})
});
Check these out with Postman. Can you successfully delete and update comments?
Now, in CommentBox.js, we need to add update and delete handling:
//...
handleCommentDelete(id) {
$.ajax({
method: 'DELETE',
url: `${this.props.url}/${id}`
})
.then((res) => {
console.log('Comment deleted');
}, (err) => {
console.error(err);
});
}
handleCommentUpdate(id, comment) {
//sends the comment id and new author/text to our api
$.ajax({
method: 'put',
url: `${this.props.url}/${id}`,
data: comment
})
.then(res => {
console.log(res);
}, err => {
console.log(err);
})
}
//...
Make sure to also bind these in this constructor:
this.handleCommentDelete = this.handleCommentDelete.bind(this);
this.handleCommentUpdate = this.handleCommentUpdate.bind(this);
...and finally, update our render() method to include update and delete:
//...
render() {
return (
<div style={ style.commentBox }>
<h2 style={ style.title }>Comments:</h2>
<CommentList
onCommentDelete={ this.handleCommentDelete }
onCommentUpdate={ this.handleCommentUpdate }
data={ this.state.data }/>
<CommentForm onCommentSubmit={ this.handleCommentSubmit }/>
</div>
)
}
//...
We also need to update our CommentList.js function with the new handlers:
//CommentList.js
import React, { Component } from 'react';
import Comment from './Comment';
import style from './style';
class CommentList extends Component {
render() {
let commentNodes = this.props.data.map(comment => {
return (
<Comment
author={ comment.author }
uniqueID={ comment['_id'] }
onCommentDelete={ this.props.onCommentDelete }
onCommentUpdate={ this.props.onCommentUpdate }
key={ comment['_id'] }>
{ comment.text }
</Comment>
)
})
return (
<div style={ style.commentList }>
{ commentNodes }
</div>
)
}
}
export default CommentList;
Our Comment.js also needs to incorporate Updating:
//Comment.js
import React, { Component } from 'react';
import style from './style';
import marked from 'marked';
class Comment extends Component {
constructor(props) {
super(props);
this.state= {
toBeUpdated: false,
author: '',
text: ''
};
//binding all our functions to this class
this.deleteComment = this.deleteComment.bind(this);
this.updateComment = this.updateComment.bind(this);
this.handleAuthorChange = this.handleAuthorChange.bind(this);
this.handleTextChange = this.handleTextChange.bind(this);
this.handleCommentUpdate = this.handleCommentUpdate.bind(this);
}
updateComment(e) {
e.preventDefault();
//brings up the update field when we click on the update link.
this.setState({ toBeUpdated: !this.state.toBeUpdated });
}
handleCommentUpdate(e) {
e.preventDefault();
let id = this.props.uniqueID;
//if author or text changed, set it. if not, leave null and our PUT request
//will ignore it.
let author = (this.state.author) ? this.state.author : null;
let text = (this.state.text) ? this.state.text : null;
let comment = { author: author, text: text};
this.props.onCommentUpdate(id, comment);
this.setState({
toBeUpdated: !this.state.toBeUpdated,
author: '',
text: ''
})
}
deleteComment(e) {
e.preventDefault();
let id = this.props.uniqueID;
this.props.onCommentDelete(id);
console.log('oops deleted');
}
handleTextChange(e) {
this.setState({ text: e.target.value });
}
handleAuthorChange(e) {
this.setState({ author: e.target.value });
}
rawMarkup() {
let rawMarkup = marked(this.props.children.toString());
return { __html: rawMarkup };
}
render() {
return (
<div style={ style.comment }>
<h3>{this.props.author}</h3>
<span dangerouslySetInnerHTML={ this.rawMarkup() } />
<a style={ style.updateLink } href='#' onClick={ this.updateComment }>update</a>
<a style={ style.deleteLink } href='#' onClick={ this.deleteComment }>delete</a>
{ (this.state.toBeUpdated)
? (<form onSubmit={ this.handleCommentUpdate }>
<input
type='text'
placeholder='Update name...'
style={ style.commentFormAuthor }
value={ this.state.author }
onChange= { this.handleAuthorChange } />
<input
type='text'
placeholder='Update your comment...'
style= { style.commentFormText }
value={ this.state.text }
onChange={ this.handleTextChange } />
<input
type='submit'
style={ style.commentFormPost }
value='Update' />
</form>)
: null}
</div>
)
}
}
export default Comment;
And finally, our CommentForm.js needs to be updated:
//CommentForm.js
import React, { Component } from 'react';
import style from './style';
class CommentForm extends Component {
constructor(props) {
super(props);
this.state = { author: '', text: '' };
this.handleAuthorChange = this.handleAuthorChange.bind(this);
this.handleTextChange = this.handleTextChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleAuthorChange(e) {
this.setState({ author: e.target.value });
}
handleTextChange(e) {
this.setState({ text: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
let author = this.state.author.trim();
let text = this.state.text.trim();
if (!text || !author) {
return;
}
this.props.onCommentSubmit({ author: author, text: text });
this.setState({ author: '', text: '' });
}
render() {
return (
<form style={ style.commentForm } onSubmit={ this.handleSubmit }>
<input
type='text'
placeholder='Your name...'
style={ style.commentFormAuthor}
value={ this.state.author }
onChange={ this.handleAuthorChange } />
<input
type='text'
placeholder='Say something...'
style={ style.commentFormText}
value={ this.state.text }
onChange={ this.handleTextChange } />
<input
type='submit'
style={ style.commentFormPost }
value='Post'/>
</form>
)
}
}
export default CommentForm;
Whew! that was a lot of code. Congrats, you have completed a MERN app!