Posting Comments Using AJAX

Developing the CMS for Linuxphile has been an iterative process.  I started with the authentication, which Laravel made, extremely simple, moved on to the content management side by reviewing editors, playing with a few, and integrating file browser and upload features in to each of the editors I reviewed. After the content piece was complete I worked on displaying the individual posts.  Recently, I have added the functionality for visitors to comment on posts. Go ahead, look below, you'll see the comment section and leave me some feedback.  I will likely be updating the display of the comments, but the basic idea is covered below. 

 CREATE TABLE comments (
  id int(10) unsigned NOT NULL AUTO_INCREMENT,
  posts_id int(11) NOT NULL,
  name varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  email varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  comment varchar(500) COLLATE utf8_unicode_ci NOT NULL,
  in_response_to int(11) DEFAULT NULL,
  created_at datetime DEFAULT NULL,
  updated_at datetime DEFAULT NULL,
  PRIMARY KEY (id));

Most of the above is self explanatory, and is fairly simple.  I could expand on this table a bit, for example by making posts_id a foreign key back to the posts table, but for demonstration purposes this will suffice.  I have added a field for future use/implementation: in_response_to.  This int field will be used to note if a comment is in reply to another comment on the same topic.  I'll expand on the comment functionality later to display the comments in comment->response format. 

In Laravel, as you may know, you have your router (routes.php), model, view and controller.  So let's start by adding our route to app\Http\routes.php:

 Route::post('/post/comment', ['as' => 'postComment', 'uses'=>'PostsController@postComment']);

You will notice in the above that comments can only be made using the POST method. Also, notice that I didn't create a controller for comments on its own.  I chose to use the PostsController because there are really only two functions needed for comments.

  1. Post Comment (user adds a new comment)
  2. Delete Comment (admin deletes inappropriate/unwanted comments)

Next we will need to modify the Posts model to reference the Comments table and then create the comments model. 

Posts Model Modification

     public function comments(){
        return $this->hasMany('App\Comments');
    }

Comment Model

 <?php namespace App;

use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;

class Comments extends Model {

	//
    public function getCreatedAtAttribute($attr) {
        return Carbon::parse($attr)->format('m/d/Y - h:ia'); //Change the format to whichever you desire
    }

    public function post() {

        return $this->belongsTo('App\Posts');
    }

}

Now on to the controller.  I'm only going to cover the method for posting the comment.  Deleting can be determined by reviewing the below code to post. 

 public function postComment(){
        $comment = new Comments();
        $comment->posts_id = Input::get("postId");
        $comment->email = Input::get("email");
        $comment->name = Input::get('name');
        $comment->comment = Input::get("comment");
        if ($comment->save()){
            return json_encode($comment);
        }else {
            return json_encode(["error"=>"Error saving comment"]);
        }
    }

Notice how, the function name corresponds to the PostsController@postComment referenced in the routes.php snippet above? Good. 

With all that out of the way we now need to modify the view that displays the posts.  For brevity's sake I'm only going to show the javascript code and relevant sections of my Posts view. 

Ok, we'll start with the javascript code, the HTML code, and an explanation of what is being done therein.

Javascript/Jquery/AJAX Call

         $(document).ready(function (){
            //ajax call for posting comments
            $("#postComment").click(function postComment() {
                $.ajax({
                            url: "/post/comment",
                            method: "POST",
                            dataType: "json",
                            data: {
                                _token: $("input[name=_token]").val(),
                                postId: $("#postId").val(),
                                name: $("#cUsername").val(),
                                email: $("#cEmail").val(),
                                comment: $("#cComment").val()
                            },

                            success: function (data) {
                                $("#cUsername").val("");
                                $("#cEmail").val("");
                                $("#cComment").val("");
                               var row = document.createElement("div");
                                row.className = 'row';
                                row.innerHTML = "<div class='col-md-12'><strong>"+data.name+"</strong> wrote on "+data.created_at+" <br/><hr/><p>"
                                    + data.comment + "</p>";
                                $("#comments").append(row);
                                oldCLink = $('#totalComments').text();
                                i = oldCLink.indexOf(" ");
                                j = oldCLink.substr(0, i);
                                j++;
                                $('#totalComments').text(j + " Comments");
                            },
                            failure: function (xhr) {
                                alert(xhr);
                            }
                        }
                );
            });

        });

HTML

                <div class="panel-body" id="commentSection">
                    <div id="comments" class="comments">
                        <a name="comments"></a>
                    @foreach($post->comments as $comment)
                        <div class="row">
                            <div class="col-md-12">
                            <strong>{!! $comment->name !!}</strong> wrote on {!! $comment->created_at !!}:
                            <p>{!! $comment->comment !!}</p>
                                <hr/>
                            </div>
                        </div>
                    @endforeach
                    </div>
                    <form id="commentForm" class="form-group">
                        <input type="hidden" id="postId" name="postId" value="{!!$post->id!!}"/>
                        <input type="hidden" name="_token" value="{{ csrf_token() }}">
                        <div class="row">
                            <div class="col-md-3">
                                <label class="control-label">Name: </label>
                                <input type="text" name="username" id="cUsername" class="form-control"/>
                            </div>

                            <div class="col-md-4">
                                <label class="control-label">Email: </label>
                                <input type="email" name="email" id="cEmail" class="form-control"/><br/>
                            </div>

                            <div class="col-md-5"></div>
                        </div>
                        <div class="row">
                            <div class="col-md-12">
                                <label class="control-label">Comment: </label><br/>
                                <textarea class="form-control" rows="5" name="comment" id="cComment"></textarea><br/>
                            </div>
                        </div>
                        <a href="#comments" id="postComment" class="btn btn-danger btn-large"><i class="glyphicon glyphicon-plus-sign"></i> Post Comment</a>
                    </form>
                </div>

Ok, so the Javascript first starts by telling the page to register an event listener when the users clicks the anchor with an id of "postComment".  That event listener then makes an AJAX call to /post/comment, specifying that the type of data return expected is JSON, using a method of POST, with the id of the post in question and the details of the post.   When the post of the comment is successful the comment is appended to the section with the id of "comments" and the total comments are incremented, with the script ending with reseting the comment fields back to empty or blank.  

1 Comments
wrote on 03/31/2017 - 08:13pm:

lllll





Post Comment