Paulund

VueJS - Building A Comments Section

To carry on through the learning of VueJS we're going to build a real world example of creating a comments section in your website. We're going to use an API to populate the comments section and another API endpoint to post new comments. When developing in JavaScript the majority of the ways you get data to show on the screen is through APIs, these will return JSON format of data and parsed by Vue to display content on the page.

The HTML

First we need to start off by adding the HTML to the page, for this comments section we're just going to have one HTML tag of comments.

<div id="app">
    <comments></comments>
</div>

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vue-resource.min.js"></script>
<script src="./js/app.js"></script>

Vue Components

Before we get started we need to think about the design of the application for the comments section and the parent-child structure of the different components. At the top level we have a comments wrapper component that will house a list of comments and a comments form. The comments form will be made up of a number of fields such as name, email and message. The list of comments will need to consist of multiple comment nodes. The comment node must consist of of the commented name and the commented message.

  • Comments wrapper
    • Comment List
      • Nodes of comments - Name - Text
    • Comment form

Comment Node

Starting from the bottom up lets build the comment node, this will be a a div with a title of the comment name, a paragraph for the comment text. The comment data is going to be passed into the comment by using a prop of commentdata.

Vue.component('comment', {
    template: '<div class="comment">' +
            '<h2>{{ commentdata.name }}</h2>' +
            '<p>{{ commentdata.text }}</p>' +
            '<hr/>' +
    '</div>',
    props: ['commentdata']
});

Comment List

The comment list component will loop through the comment data and pass each node into a comment node. To loop through all the comments we need to accept a prop of comments then use the for loop v-for="commentdata in comments" and pass in the commentdata on the component prop.

Vue.component('comment-list', {
    template: '<div class="comment-list"><comment v-for="commentdata in comments" v-bind:commentdata="commentdata"></comment></div>',
    props: ['comments']
});

Comment Form

The comment form will be a simple form with Name, Comment and a submit button. On the submit event of the comment form we then run the method postComment. On the input textbox and the textarea there are v-model directives for name data property and text data property. We need this so we can access these values inside the postComment method. Inside the postComment method we then need to collect the name and text from the form, add these to a new object then post these to the API url. To perform API calls in VueJS you need to use a plugin called vue-resource. On the success event of the api we need to push the comment into the parent comments list to automatically show the comment on the list.

Vue.component('comment-form', {
    template: '<form v-on:submit.prevent="postComment">' +
        '<p><label for="name">Name</label><input type="text" name="name" id="name" v-model="name" placeholder="Enter name"></p>' +
        '<p><label for="text">Comment</label><textarea name="text" id="text" v-model="text" placeholder="Enter comment"></textarea></p>' +
        '<p><label for="submit"></label><button name="submit" id="submit" class="btn btn-primary">Submit</button></p>' +
    '</form>',
    data: function(){
        return {
            name: '',
            text: ''
        };
    },
    methods: {
        postComment: function()
        {
            var comment = { 'name': this.name, 'text': this.text };

            // POST /someUrl
            this.$http.post('/api/comments', comment).then((response) => {
                this.$parent.comments.push(comment);
            }, (response) => {
                console.log('Error');
            });
        }
    }
});

Comment Wrapper

The comment wrapper is made up of the comment list and the comment form, the comment list needs to pass comments into the child object. Therefore we need the comments object to get all the comments on the load even of the page. For this we use one of VueJS lifecycle functions of created, inside here we're going to make an api call using this.$http.get to get a list of comments and put this into the comments data property.

Vue.component('comments', {
    template: '<div class="comments"><comment-list v-bind:comments="comments"></comment-list><comment-form></comment-form></div>',
    data: function()
    {
        return {
            comments : []
        }
    },
    created: function()
    {
        return this.$http.get('/api/comments').then((response) => {
            this.comments = response.body;
        });
    }
});

With all the components built we just need to create the Vue object to start the app.


var app = new Vue({
    el: '#app',
})

There is no demo for this tutorial because it uses an API to get and post the comments. In the download files on Github I've included a node server script and a data file for the comments. This node server script will create an API which can be used to demo this tutorial on your local machine. You'll be able to get all the comments from the file inside the /data/ folder and see them displayed on the page, when you fill out the comments form you comment will be posted to the comments.json file. If you have any questions with this tutorial please ask.