Vue.js for Interactive Web Interfaces

vuejs

Angular by Google and React by Facebook are two of the most popular JavaScript Frameworks as of today. Vue.js is what we’ll cover in this Vue.js tutorial, so let’s take a slight turn and look at what this fantastic MVVM framework called Vue.js has to offer. Vue.js makes building interactive web interfaces easier via two way data bindings. Simplicity is a goal of Vue.js, especially as compared to some of the other popular JS offerings. Let’s have a look at Vue.js now.


Try out the Todo app demo

Installing Vue.js for the first time.

The best way to learn something is to simple start getting your hands dirty right away. That’s what we’ll do with Vue.js right now. In order to create a code sandbox for us to work with, we’ll create this simple application directory like so.

vue.php


<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Vue.js</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
</head>
<body>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.14/vue.min.js"></script>
<script src="vue.js"></script>
</body>

</html>

With this configuration we have access to all of the features of Vue.js via a content delivery network, as well as some css styling via the bootstrap framework, also from a CDN. This way, it is simple to build out our code playground in about 10 seconds.

Two way data binding with Vue.js

Moving right along, we can set up our first two way data binding instance with Vue.js. We’ll add a container with an id, then implement a new Vue instance and bind it to the element we just created.

Element to bind to

<div class="container">
    <div id="todo">{{ hello }}</div>
</div>

Vue.js instance

new Vue({
    el: '#todo',

    data: {
        hello: 'This is a two way data bind'
    }
})

Result in the browser

two way data bind vuejs

Think of the placeholder in between the mustache curly braces (in this case hello) as a variable that simply grabs the data that is in the property of the same name of the data object in the Vue instance. I know, sounds a little tricky, but it does make sense. Let’s demonstrate the two way data binding further with an input element.

Vue.js v-model

<div class="container">
    <div id="todo">{{ hello }}
        <input v-model="hello">
    </div>
</div>

Result in the browser

two way data binding example two
Anything that gets typed into the input is immediately updated in the dom. Very cool.

The Language of Vue.js

Before we go too much further, it would help to review some of the constructs of the language itself. Vue.js works by applying various attributes to your raw HTML so that your JavaScript and Vue instances can easily interact with those elements in the dom. Here are some of the v-* constructs, which are referred to as directives, to be aware of.


v-on

The v-on directive is used to add an event listener to the element. For example, when building a Todo application, we can use the v-on directive in a form like so.

<form v-on:submit="addTodo">

This will add an event listener for the submit action on a form.


v-model

The v-model directive is used to create a two way binding to a form input element. It can be used on <textarea>, <select>, and <input> tags as needed.
An example in a Todo app might be like so.


<input v-model="newTodo"
       v-el="newTodo"
       class="form-control"
       placeholder="What do you need to do?">
</input>


v-el

The v-el directive registers a reference to a dom element to the corresponding Vue instance. We can see a use case in the prior snippet where we demonstrate the v-model.


v-show

The v-show directive is used to set off transitions. In other words, if you take action on an element in the dom which interacts with a Vue instance, a different portion of the dom can be updated in real time. For the Todo app, we can show items we finish with something like this.


<div v-show="pending.length">
    <h1>todo ({{ pending.length }})</h1>

    <ol class="list-group">
        <li v-for="todo in pending"
            class="list-group-item"
            >
            <span v-on:dblclick="editTodo(todo)">{{ todo.body }}</span>

            <button v-on:click="deleteTodo(todo)" class="btn btn-default"><span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button>
            <button v-on:click="toggleTodoCompletion(todo)" class="btn btn-default"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></button>
        </li>
    </ol>
</div>

v-repeat

v-for is often used to display a list. It is populated by an array of objects in the ViewModel. Each object in the array gets a child Vue instance created. In the snippet above, you can see how by combining v-show with v-for, we can output lists of items in real time.

The Vue.js directives are automatically bound to a property on your Vue instance. When the value of the underlying property changes, so to does the view by way of an update() function. Learn about all of the Vue.js directives right at the official documentation.

The Structure of a Vue.js App

If you were to stub out a Todo application with Vue.js, it may look a bit like this.

new Vue({

    el: '#todos',

    data: {

    },

    computed: {

    },

    methods: {

    }

});

We can see that this is an object of objects. el is the Vue instance in the dom represented by a string (css selector). data is an object and refers to the data object of the Vue instance, for which we can import and export information to and from. computed is a special object which holds properties to be mixed in to the Vue instance. The this keyword is bound to the Vue instance. methods are where all of your functions get defined, and they can be called from the directive, or directly on the VM instance.

Creating a Todo App

Now that we have Vue.js installed and we have investigated some of the basic concepts of how it works, let’s build a simple Todo application which runs as a single page application in the browser.

Adding Todo Items

Our fist goal is to be able to display a form on the page with a submit button. When we type some data into the form, then click submit, it should then update in real time on the same webpage with no reloading of the browser. Here is how we can do that with Vue.js.

Our Todo HTML

<div class="container">
    <div id="todos">

        <form v-on:submit="addTodo">
            <div class="form-group">
                <input v-model="newTodo"
                       class="form-control"
                       placeholder="What do you want to do?">
                </input>
            </div>

            <button class="btn btn-info">
                Add a Todo
            </button>
        </form>

        <div>
            <h1>Things to do</h1>

            <ol class="list-group">
                <li v-for="todo in todos" class="list-group-item">
                    {{ todo.body }}
                </li>
            </ol>
        </div>

    </div>
</div>

Vue.js code

new Vue({
    // the Vue Instance
    el: '#todos',

    // the data object,
    // todos is where we collect to do items
    // newTodo data binds to the form input
    data: {
        todos: [
            { body: 'Eat a Sandwich', completed: false }
        ],

        newTodo: ''
    },

    methods: {
        // function declarations
        addTodo: function (e) {

            // prevent the HTML form from submitting to the server
            e.preventDefault();

            this.todos.push({
                body: this.newTodo,
                completed: false
            });

            // simply set the form input field to an empty string
            // after we add a todo item
            this.newTodo = '';
        }
    }
});

add items to an array Vue js

Deleting A Todo Item

Now that we can successfully add items to our Todo list, let’s now implement a way to delete the items from the list with the click of a button. First off, we need to add some type of visual indicator to our HTML to show the intent to delete an item. Recall, that we use the v-repeat directive to loop over all of the todo items. All we have to do is add a button like so.


<ol class="list-group">
    <li v-for="todo in todos" class="list-group-item">
        {{ todo.body }}
        <button v-on="click: deleteTodo(todo)" class="btn btn-default"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
    </li>
</ol>

This is pretty readable. Where you can see the button, it simply says when you click this button, call the deleteTodo function and pass in the current iteration of the todo during this looping process of v-repeat. Now just add the deleteTodo function to our method object and we should be good to go.

 
       // the deleteTodo function
        deleteTodo: function(todo) {
            this.todos.$remove(todo);
        }

We go get a drink of water, click the delete button, and voila – it is gone.
vue js delete items

Edit a Todo in 3 Lines of code

Now let’s add the ability to edit an item. All we have to do is add a new button with an edit symbol attached, associate that to an on click event that will fire an editTodo method, and provide a name to the element that we want to give focus to.

Adding the edit button

<ol class="list-group">
    <li v-for="todo in todos" class="list-group-item">
        {{ todo.body }}
        <button v-on:click="deleteTodo(todo)" class="btn btn-default"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
        <button v-on:click="editTodo(todo)" class="btn btn-default"><span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button>
    </li>
</ol>

Add v-el=”newTo” to the input

<input v-model="newTodo"
       v-el="newTodo"
       class="form-control"
       placeholder="What do you want to do?">
</input> 

Add the editTodo function

editTodo: function (todo) {
	// delete the task we click on
	this.deleteTodo(todo);
	// load the body of the current object so we can edit it
	this.newTodo = todo.body;
	// add focus to this element
	this.$$.newTodo.focus();
}

Change the time at which we want to eat a sandwich.
edit item vuejs
edit example vuejs

Mark A Todo Item as Complete

So far we can add a Todo item as well as edit or delete a Todo item from our list. Let’s add a simple way to mark a todo item as completed. In order to keep track of items that are complete, we need to make use of a new topic we have not covered yet, and that is filtering. We actually need two different areas now to show items, one where items are pending, and one where items are already finished. First let’s update the HTML to support these two different categories.


<div v-show="pending.length">
    <h1>Things to do ({{pending.length}})</h1>

    <ol class="list-group">
        <li v-for="todo in pending" class="list-group-item">
            {{ todo.body }}
            <button v-on:click="deleteTodo(todo)" class="btn btn-default"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
            <button v-on:click="editTodo(todo)" class="btn btn-default"><span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button>
            <button v-on:click="markComplete(todo)" class="btn btn-default"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></button>
        </li>
    </ol>
</div>

<div v-if="finished.length">
    <h2>Completed ({{finished.length}})</h2>

    <ol class="list-group">
        <li v-for="todo in finished" class="list-group-item">
            {{ todo.body }}
            <button v-on:click="deleteTodo(todo)" class="btn btn-default"><span class="glyphicon glyphicon-minus-sign" aria-hidden="true"></span></button>
        </li>
    </ol>

    <button v-on:click="clearCompleted" class="btn btn-danger">Clear All Completed Items</button>
</div>

In the snippet above, you can see that we are referencing a pending and finished property in our code. Let’s see what this corresponds to in the JavaScript side.

new Vue({
    // the Vue Instance
    el: '#todos',

    // the data object,
    // todos is where we collect to do items
    // newTodo data binds to the form input
    data: {
        todos: [
            { body: 'Eat a Sandwich', completed: false }
        ],

        newTodo: '',

        filters: {
            notDone: function(todo) {
                return ! todo.completed;
            },

            completed: function(todo) {
                return todo.completed;
            }
        }
    },

    computed: {
        finished: function () {
            return this.todos.filter(this.filters.completed);
        },

        pending: function () {
            return this.todos.filter(this.filters.notDone);
        }
    },
});

The definition of filters from the documentation.

A Vue.js filter is essentially a function that takes a value, processes it, and then returns the processed value. In the markup it is denoted by a single pipe (|) and can be followed by one or more arguments.

We also make use of the computed object, and this is defined as follows.

Vue.js’ inline expressions are very convenient, but the best use cases for them are simple boolean operations or string concatenations. For more complicated logic, you should use computed properties.

Add the markComplete function

// mark one item as complete, one at a time
markComplete: function (todo) {
	todo.completed = true;
}

This function will mark a pending item as finished, and our filters will move the todo item from the pending list to the finished list in the corresponding HTML.

Marking items as complete

Finally, we can add two functions to either complete all todo items, which will move them from the pending to the finished list, in addition to adding a function to mark all finished items as complete and remove them from the finished list.

// mark all items as complete by looping over them
completeAll: function () {
	this.todos.forEach(function (todo) {
		todo.completed = true;
	});
},

// clear all completed items
clearCompleted: function () {
	this.todos = this.todos.filter(this.filters.notDone);
}

The corresponding HTML these functions act on are here.

<button v-on="click: completeAll" class="btn btn-default">Mark All As Completed?</button>

<h2>Completed ({{finished.length}}) <small v-on="click: clearCompleted" class="btn btn-danger">Clear All Completed Items</small></h2>   

Vue.js for Interactive Web Interfaces

Vue.js is a great JavaScript framework that is fun to use, and quite flexible. In this tutorial, we had a look at some of the basics of how to use it, and you can even try the little app at the top of this post. Vue.js is one framework to keep your eye on.