How to use Bugfender with a Vue.js application
Tags: javascript, technology
Published: 2021-04-26 22:19:02

---
title: How to use Bugfender with a Vue.js application
published: true
date: 2021-03-08 21:11:23 UTC
tags: JavaScript,Technology
canonical_url: https://bugfender.com/blog/how-to-use-bugfender-with-a-vue-js-application/
---

It is an exciting era for web developers with so many open-source frameworks and libraries around to help them. Of all the frameworks that have emerged in recent years, `Vue.js` stands out for its simplicity, adaptability and rapid load times.

In this article, we will learn how to get started with Vue.js. We will also go through the steps to integrate and use `Bugfender` with a Vue.js application.

# What are we building today?

We will build a simple `TODO` application, which will enable us to add, fetch, edit, and delete TODO items. Though the app sounds simple, we will learn the concept of CRUD (Create-Read-Update-Delete) operations using a Vue.js application.

In the later part, we will integrate `Bugfender` APIs to log the activities from the application. Lastly, we will use some of Bugfender’s advanced features, like `send feedback` , to send user feedback from the TODO app to the Bugfender log server.

At any point in time, you can have a look at the code in the [GitHub repository](https://github.com/atapas/vue-todo).

And you can also play around with the app from [here](https://bugfender-todo.vercel.app/).

# Vue.js – installation, setup, and structure

Vue.js is a progressive web app framework that helps build the view part of the MVC (Model-View-Controller) paradigm. It empowers you to build single-page applications using the core Vue.js library and its tooling ecosystem.

## Installation

To install and work with Vue.js, we need to have `Node.js` installed. If you do not have Node.js installed, please download and install it [from here](https://nodejs.org/en/download/current/). Node.js comes with the `npm` utility that we will use to install other packages. Alternatively, you can also use `yarn` for installing packages.

> Please note, unlike other UI libraries/frameworks, Vue.js provides an option to include the library from the CDN. You can use the CDN URL to include the `Vue.js` in your project’s script tag. However, in a production-like application, you cannot do that. Instead, you are obliged to rely on a Node.js-based environment. So this article doesn’t cover the CDN-based approach in great detail.

First we will install `vue-cli`. The vue-cli is a command line utility to manage your Vue.js app. To access it, open a command prompt and install `vue-cli`.

```
npm install -g @vue/cli
# OR
yarn global add @vue/cli
```

It will take a while to install the vue-cli globally. This means you will be able to access Vue.js from anywhere on your computer drives, using the binary name `vue`. Check tgat the cli is installed correctly using this command.

```
vue --version
```

If all is good, you should see the vue-cli version printed in the console.

## Setup

Next, we will create a Vue.js project using the `vue-cli` tool. You can use the following command to create a Vue.js project structure with required libraries.

```
vue create vue-todo
```

The command `vue create <app-name>` creates a Vue.js app with a given name. In our case, the app name is `vue-todo`. You will be asked to select the `Vue.js` version to create the app. You can proceed by selecting either the Vue 2 or Vue 3 Preview option.

> Please note: If you are using `GitBash` as your command prompt, the interactive menu may not work well. In that case, please use this command: `winpty vue.cmd create vue-todo`

[![](https://bugfender.com/wp-content/uploads/2021/03/Untitled.png)](https://bugfender.com/wp-content/uploads/2021/03/Untitled.png)<figcaption>Figure 1: Select Vue.js version</figcaption>

Press select the item and press the enter key to complete the setup. Once completed, you will find a project folder created with the app name you typed in the create command. In our case, it is `vue-todo`. Now you can import the project folder in your favorite source code editor.

At this point, it should have the following structure:

[![](https://bugfender.com/wp-content/uploads/2021/03/Untitled-1.png)](https://bugfender.com/wp-content/uploads/2021/03/Untitled-1.png)<figcaption>Figure 2: Initial Project Structure in the VS Code</figcaption>

Now let’s run the app. In the command prompt, use this command to run the application:

```
npm run-serve
# OR
yarn serve
```

It will compile the app and deploy it on a local server. By default, the app will run on the URL [`http://localhost:8080/`](http://localhost:8080/). Access this URL from your favorite browser. You should see a page like this:

[![](https://bugfender.com/wp-content/uploads/2021/03/Untitled-2-1024x522.png)](https://bugfender.com/wp-content/uploads/2021/03/Untitled-2.png)<figcaption>Figure 3: Initial page.</figcaption>

## Structure

Let’s take a look at some of the important folders and files to understand how the Vue.js project structure works in practice. First, open the file called `index.html` under the `public` folder. Notice the line

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

This `div` with the id `app` is the wrapper of our entire application. You can think of it as the root of the application we are going to build.

Next, open the `main.js` file under the `src` folder. This file is the entry point of a Vue.js application. Let’s have a look at the content:

```
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')
```

- First, we import the method `createApp` from the `vue`.
- We import a component called `App` from the file `App.vue`. We will see this component in more detail in a while.
- Lastly, we create the app using the `App` component and mount it to the root element which is a div with the id `app`. We have seen this div already in the `index.html` file.

Finally, let’s have a look into a Vue.js component. We already have a component created for us: `App.vue`. Open the file and you’ll notice that there are three primary sections.

```
<template>
...
</template>

<script>
...
</script>

<style>
...
</style>
```

It is a standard structure for any Vue.js component. The HTML part of the component goes inside the `<template>` tags, the data and script portion goes inside the `<script>` tags and the `<style>` tags contains the component styles.

The structure may seem a bit strange at first glance. You may feel that there is no separation of the HTML, Script, Data, and Style. But if you think about it from a component perspective, each of the components is an isolated unit. They have their data, template, script, and style composed within.

# The TODO app

At the end the TODO app will look like this:

[![](https://bugfender.com/wp-content/uploads/2021/03/app.png)](https://bugfender.com/wp-content/uploads/2021/03/app.png)<figcaption>Figure 4: TODO app Final Version</figcaption>

As you see, it has:

- A header.
- A text-box and a button to create a TODO item.
- A table below to list all the TODO items with options to edit and delete them.

At a high level we can then divide the TODO app into two major components:

- TodoForm.vue ⇒ This component will contain the text-box and button for the ‘TODO item create’ action.
- TodoTable.vue ⇒ This component will contain the table to list the TODO items along with the buttons to edit and delete them.

Finally, these two components can be combined into the `App.vue` component.

[![](https://bugfender.com/wp-content/uploads/2021/03/app-structure.png)](https://bugfender.com/wp-content/uploads/2021/03/app-structure.png)<figcaption>Figure 5: App Structure</figcaption>

## TODO app – The `TodoForm` component

Now create a file called `TodoForm.vue` inside the `src\components` folder, with the following content:

```
<template>
  <div id="todo-form">
    <form @submit.prevent="handleSubmit">
      <label>Add a TODO</label>
      <input v-model="todo.name" type="text" />
      <button>Add</button>
    </form>
  </div>
</template>

<script>
  export default {
    name: 'todo-form',
    data() {
      return {
        todo: {
          name: ''
        },
      }
    },
    methods: {
        handleSubmit() {
            this.$emit('add:todo', this.todo)
        },
    },
  }
</script>

<style scoped>
  form {
    margin-bottom: 2rem;
  }
</style>

```

- First, we are creating the `template` for the component. The template has a form with an input text box, and a button. The text box has an attribute called `v-model` , which helps to convey the data from the text-box to Vue’s component state.
- The form has an attribute `@submit.prevent="handleSubmit"` which is Vue.js’s syntax for adding an event handler. In this case, we are adding an `onSubmit` event handler. We are specifying to call a method `handleSubmit` when the user submits this form by clicking the button.
- Next, lets move towards the `script` section of the component. We define the name of the component as `todo-form`. This name will be applied when we use this component in the template of the `App.vue` component. We can also define the data as the `todo` object with a property called `name`. This structure is important as this property(`todo.name`) has a bind with the text-box using the `v-model` attribute. Hence Vue.js will take care of updating the name property value when the value of the text-box gets updated.
- The purpose of the `methods` section of a component is to define all the methods required to support its functionality. In this case, we need to handle the submission of the form. Hence we define the `handleSubmit()` method.
- The `handleSubmit()` method broadcasts the name of an event and data to its parent component using the `$emit()` method. In this case, the event name is `add:todo` and the data is the `todo` object itself.
- Finally, the `style` section contains the styling(CSS) for the component. Notice the `scoped` attribute there. It means the styles are scoped for this component alone.

Great! Now we will import and use the `TodoForm` component in the `App.view` component. Replace the `<script>` section of the component with the following code:

```
<script>
import TodoForm from "@/components/TodoForm.vue";

export default {
  name: 'App',
  components: {
    TodoForm
  }
}
</script>

```

- Here we are importing the `TodoForm.vue` component. Please note the `@` symbol in the path. It refers to the `src` folder.
- Next, in the `componenents` list, we add the TodoForm as an entry.

Now it’s the time to change the `<template>` section of the `App.vue` component. Please replace it with the following code:

```
<template>
   <div id="app" class="small-container">
    <h1>Bugfender TODO</h1>
    <todo-form />
  </div>
</template>

```

- Note: we have a header that says `Bugfender TODO` and then we use the `<todo-form>` just below it. As you refresh your browser, the form will display like this:

[![](https://bugfender.com/wp-content/uploads/2021/03/Untitled-3.png)](https://bugfender.com/wp-content/uploads/2021/03/Untitled-3.png)<figcaption>Figure 6: The TODO Form</figcaption>

Hold on! What about that event we broadcasted to add a TODO item? To manage this event, we need to add the attribute `@add:todo="addTodo"` to the `<todo-form>` in the template of `App.vue`.

```
<todo-form @add:todo="addTodo"/>
```

Next, add a `methods` section in the `<script>` tag:

```
export default {
  name: 'App',
  components: {
    TodoForm
  },
  methods: {
    addTodo(todo) {
      console.log(todo);
    }
  }
}
```

At this point, we are just logging the todo object into the browser console. Go ahead and add a TODO item in the text box and click on the button. You should see the todo information logged in the console. This means the text change in the input box is changing the state of the application and we are able to use it elsewhere.

[![](https://bugfender.com/wp-content/uploads/2021/03/Untitled-4-1024x231.png)](https://bugfender.com/wp-content/uploads/2021/03/Untitled-4.png)<figcaption>Figure 7: Todo item add logging</figcaption>

## TODO app – The `TodoTable` component

Now we will focus on implementing the `TodoTable` component to list all the TODO items. Before we do so, let’s make a small change in the `todos` data structure. We would like to maintain an `id` property for each of the TODO items; this will help us to find a specific TODO item with its id, and then edit or delete it.

Let’s use a npm called `shortid` that generates a random id to use. Open a command prompt, browse to your project folder and try this command:

```
 npm install shortid
 # OR
 yarn add shortid
```

Next, import the `generate()` function of the `shortid` inside the `<script>` tag of the `App.vue` component.

```
import { generate } from 'shortid';
```

Now we will add a `data()` method to the script section to initialize the TODO app with three default todo items.

```
<script>
... imports

export default {
  name: 'App',
  components: {
    ... components
  },
  data() {
    return {
      todos: [
        {
          id: generate(),
          name: "Log a Defect"
        },
        {
          id: generate(),
          name: "Exercise"
        },
        {
          id: generate(),
          name: "Buy Milk"
        },
      ],
    };
  },
  methods: {
    ...methods
  }
}
</script>

```

Notice the `todos` data structure: it is an array that has both id and name. To work on this, we can start by creating the `TodoTable.vue` component. First, create a file called `TodoTable.vue` under the `components` folder with the following content:

```
<template>
  <div id="todo-table">
    <p v-if="todos.length < 1" class="empty-table">No Todos</p>
    <table v-else>
      <thead>
        <tr>
          <th><h2>TODOs</h2></th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="todo in todos" :key="todo.id">
          <td >{{ todo.name }}</td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
  export default {
    name: 'todo-table',
    props: {
        todos: Array,
    }
  }
</script>

<style scoped>
  button {
    margin: 0 0.5rem 0 0;
  }
</style>

```

- The `template` section contains the table to list the ToDo items. However there are a few things to note here: We can use the attributes like `v-if` and `v-else` for conditional statements, and likewise we can use `v-for` for looping. Here, we are checking whether the `ToDo` data structure is empty. If so, we just show a message saying `No ToDo`. In case there are `ToDo` elements (the todos data structure is not empty) we iterate over it and render the ToDo names.
  - Ok, so where is the `ToDos` data structure coming from? The source is the pops that will be injected into this component. Check out the `script` section above. We can give it the name `todo-table` and also define that the component expects a props called `todos` array.
- Finally, use `style` to define some scoped style for the component.

Now, go to the `App.vue` component and import the `TodoTable` component inside the `script` section.

```
import TodoTable from "@/components/TodoTable.vue";
```

Next, please mention it under the components section:

```
components: {
    TodoForm,
    TodoTable
  }
```

Finally, add it to the template section:

```
<template>
... existing code
  <todo-form @add:todo="addTodo"/>
	<todo-table :todos="todos" />
... existig code
</template>

```

Note: we are passing the initial `todos` array as a prop to the `todo-table` component. Now refresh your browser and see the app list down the default _ToDo’s_.

[![](https://bugfender.com/wp-content/uploads/2021/03/Untitled-5-1024x314.png)](https://bugfender.com/wp-content/uploads/2021/03/Untitled-5.png)<figcaption>Figure 8: Fetching default TODOs</figcaption>

Well, it works but it doesn’t look that great, so let’s add some overall styles to give it a better visual feel. Add the following styles inside the <style> tag of the App.vue component. Note that this style tag is not scoped, hence the styles can be applied outside the component as well.

```
button {
  background: #ff5060;
  border: 1px solid #ff5060;
  color: #FFFFFF;
  padding: 5px;
  border-radius: 4px;
  cursor: pointer;
}

.sendFeedback {
  position: absolute;
  top:10px;
  right: 30px;
}

.small-container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

table {
  border-collapse: collapse;
  margin: 25px 0;
  font-size: 0.9em;
  font-family: sans-serif;
  min-width: 400px;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
  width: 100%;
}

table thead tr {
  text-align: left;
}

table th {
  padding: 12px 25px;
}

table td {
  padding: 12px 15px;
}

table tbody tr {
  border-bottom: 1px solid #dddddd;
}

table tbody tr:nth-of-type(even) {
  background-color: #f3f3f3;
}

table tbody tr:last-of-type {
  border-bottom: 2px solid #ff5060;
}

table tbody tr.active-row {
  font-weight: bold;
  color: #ff5060;
}

label {
    font-weight: 600;
    max-width: 100%;
    display: block;
    margin: 1rem 0 0.5rem;
}

input[type=text] {
  display: block;
  border: 1px solid #dedede;
  border-radius: 4px;
  padding: 0.75rem;
  outline: none;
  background: transparent;
  margin-bottom: 0.5rem;
  font-size: 1rem;
  width: 100%;
  max-width: 100%;
  line-height: 1;
}
```

Now refresh the browser. It looks much better than before.

[![](https://bugfender.com/wp-content/uploads/2021/03/Untitled-6.png)](https://bugfender.com/wp-content/uploads/2021/03/Untitled-6.png)<figcaption>Figure 9: The app after styles applied</figcaption>

## Let’s get things together – Add, Edit, and Delete

It’s time to complete the add, edit, and delete todo functionalities.

### Add TODO Item

We have a placeholder `addTodo` method that logs a todo in the browser console. Let’s modify it to add a TODO item in the todo table. To do so, replace the `addTodo` method in the `App.vue` component with the following code:

```
addTodo(todo) {
 const id = generate();
 const newTodo = { ...todo, id };
 this.todos = [...this.todos, newTodo];
},
```

Here, we take the todo object and create a new instance by adding an id. Finally, add the new todo to the todos array. That’s all.

[![](https://bugfender.com/wp-content/uploads/2021/03/Add_TODO.gif)](https://bugfender.com/wp-content/uploads/2021/03/Add_TODO.gif)<figcaption>Figure 10: Add a TODO item</figcaption>

### Delete TODO Item

Now let’s implement the ‘delete TODO item’ functionality. Go to the `TodoTable` component and add the delete button. We will also emit a delete event and broadcast the todo id to be deleted.

```
...existing code
<tr v-for="todo in todos" :key="todo.id">
          <td >{{ todo.name }}</td>
           <td>    
            <button @click="$emit('delete:todo', todo.id)">Delete</button>
           </td>
 </tr>
...existing code

```

In the `App.vue` file add the `@delete:todo` attribute to the `todo-table` to catch the delete event.

```
<todo-table 
      :todos="todos" 
      @delete:todo="deleteTodo"/>

```

Finally, add the `deleteTodo` method in the `methods` object of the script section. Here we are just filtering out the todo we want to remove from the `todos` array.

```
deleteTodo(id) {
 this.todos = this.todos.filter(
   todo => todo.id !== id
 )
},

```

Ok, that’s about it! We have the ‘delete TODO’ item implemented.

[![](https://bugfender.com/wp-content/uploads/2021/03/Delete_TODO.gif)](https://bugfender.com/wp-content/uploads/2021/03/Delete_TODO.gif)<figcaption>Figure 11: Delete a TODO item</figcaption>

### Edit TODO Item

But what the ‘edit TODO’ item? Let me leave that one to you. But if you need any references, please check out the GitHub repo mentioned above.

Hint: You need to add an event handler to the edit button like we did for the delete. Then you need to turn on the edit mode to show the todo name in a text box. On saving the changed name, you need to turn off the edit mode and, finally, alter the `todos` array to reflect the change.

All the best!

[![](https://bugfender.com/wp-content/uploads/2021/03/Edit_TODO.gif)](https://bugfender.com/wp-content/uploads/2021/03/Edit_TODO.gif)<figcaption>Figure 12: Edit a TODO Item</figcaption>

# Logging using Bugfender

[Bugfender](https://bugfender.com/) is a remote logging service which allows users to collect logs for everything that happens in the application. It is very easy to integrate Bugfender with a JavaScript-based framework like `Vue.js` and get started. There are SDKs available to integrate with mobile applications as well.

To kick things off, simply [create an account](https://dashboard.bugfender.com/signup) with Bugfender. Once logged in, create a Bugfender application for web apps using the Web SDK option. You can follow this [step-by-step guide](https://support.bugfender.com/en/articles/118162-first-steps-with-bugfender) to create a Bugfender application, and you will find an API key ready for you. Keep it safe.

Once you have created your app, the Bugfender dashboard will enable you to keep track of logs, issues, feedback and crashes. This is how my dashboard looks:

[![](https://bugfender.com/wp-content/uploads/2021/03/Untitled-7-1024x349.png)](https://bugfender.com/wp-content/uploads/2021/03/Untitled-7.png)<figcaption>The BugFender dashboard with an app</figcaption>

## Install Bugfender SDK

Open a command prompt and the root of the project folder and use this command to install the Bugfender SDK:

```
npm i @bugfender/sdk
# Or
yarn add @bugfender/sdk 
```

## Add the Bugfender API Key

We need the Bugfender API key to communicate with its APIs. We do not want to make this API key public. So, please create a `.env` file at the root of your project folder and add a key-value pair like this,

```
VUE_APP_BUGFENDER_API_KEY=<YOUR_BUGFENDER_API_KEY>
```

Please note: All the Vue.js specific keys in the `.env` file should be prefixed with `VUE_APP_`.

## Add Bugfender Logs

Open the `App.vue` component and import the bugfender sdk:

```
import { Bugfender } from '@bugfender/sdk';
```

Then initialize the BugFender service by calling the `init` method. We pass the API key to this method.

```
Bugfender.init({
    appKey: process.env.VUE_APP_BUGFENDER_API_KEY
});
```

Now you can start adding logs of different log levels (info, warn, error, etc.) in your application code. Here is an example, in which we add a normal info log in the `addTodo` method:

```
addTodo(todo) {
    const id = generate();
    const newTodo = { ...todo, id };
    this.todos = [...this.todos, newTodo];

    Bugfender.log(`Added a TODO with id ${id}, and name ${todo.name}`);
 }
```

Similarly, you can add `deleteTodo` and `editTodo` methods as well. Now as you start adding, editing, or deleting TODO items from your app, it will log the relevant details to the Bugfender app. You can view them from the Bugfender dashboard.

Here are a few examples:

[![](https://bugfender.com/wp-content/uploads/2021/03/Untitled-8-1024x50.png)](https://bugfender.com/wp-content/uploads/2021/03/Untitled-8.png)

[![](https://bugfender.com/wp-content/uploads/2021/03/Untitled-9-1024x48.png)](https://bugfender.com/wp-content/uploads/2021/03/Untitled-9.png)

[![](https://bugfender.com/wp-content/uploads/2021/03/Untitled-10.png)](https://bugfender.com/wp-content/uploads/2021/03/Untitled-10.png)

Importantly, we can also capture other browser event logs:

[![](https://bugfender.com/wp-content/uploads/2021/03/Untitled-11-1024x336.png)](https://bugfender.com/wp-content/uploads/2021/03/Untitled-11.png)

## Bugfender – Advanced API Usages

The Bugfender SDK provides APIs for many of the advanced usages, like:

- sendIssue – To send an issue with the title and details to the Bugfender log server.

```
Bugfender.sendIssue('Issue title', 'Description of the issue');
```

- sendLog – Send logs with tags so that you can filter the log accordingly.

```
Bugfender.sendLog({ tag: 'tag1', text: 'this is my log' });
```

- sendUserFeedback – You can send user feedback using this API and see all the user feedback under the `Feedback` section of the Bugfender Dashboard.

```
Bugfender.sendUserFeedback('Love the App!', 'You are doing a great job with it.')
```

- As an additional option, we can also use the `getUserFeedback()` method to create a modal user interface for collecting the feedback.

```
Bugfender.getUserFeedback().then((result) => {
    if (result.isSent) {
        // User sent the feedback
        // `result.feedbackURL` contains the Bugfender feedback URL
    } else {
        // User closed the modal without sending the feedback
    }
});
```

In a Vue.js app, you can easily create a component for this functionality. Here is an idea of a sample `SendFeedback.vue` component (you can refer to this component [from here](https://github.com/atapas/vue-todo/blob/main/src/components/SendFeedback.vue) as well).

```
<template>
  <div class="hello">
    <button @click="sendFeedback()">Send Feedback</button>
  </div>
</template>

<script>
import { Bugfender } from '@bugfender/sdk';
export default {
  name: 'HelloWorld',
  methods: {
    sendFeedback() {
      console.log('Sending Feedback');
      Bugfender.getUserFeedback().then((result) => {
        if (result.isSent) {
            // User sent the feedback
            // `result.feedbackURL` contains the Bugfender feedback URL
            Bugfender.info('User has sent the Feedback to Bugfender', result.feedbackURL);
        } else {
            Bugfender.warn('User feedback has not been sent.');
        }
      });
    },
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

```

You can add this component anywhere in your app to collect the feedback using the modal user interface.

[![](https://bugfender.com/wp-content/uploads/2021/03/Send_Feedback.gif)](https://bugfender.com/wp-content/uploads/2021/03/Send_Feedback.gif)

You can see the feedback under the Feedback tab of your Bugfender dashboard page.

[![](https://bugfender.com/wp-content/uploads/2021/03/Untitled-12-1024x70.png)](https://bugfender.com/wp-content/uploads/2021/03/Untitled-12.png)

To drill down to it, all you need to do is click on a feedback name to see the associated logs. You can also track the feedback as a GitHub issue.

[![](https://bugfender.com/wp-content/uploads/2021/03/Untitled-13-1024x119.png)](https://bugfender.com/wp-content/uploads/2021/03/Untitled-13.png)

# Where to go from here

That’s all for now. Thanks for reading through! I hope you found the article insightful. Please start exploring `Vue.js` if you are new to it. As a next step, you can connect this TODO app to a database and persist the todo item to it.

Please explore Bugfender to find out more about other usages.

Here are a few links you may find useful:

- [Vue.js user guide](https://vuejs.org/v2/guide/)
- [Bugfender Web SDK](https://js.bugfender.com/)
- [GitHub repository of the vue-todo app](https://github.com/atapas/vue-todo). Please feel free to star/fork/contribute.

Bugfender is a tool that helps you finding errors in your production apps. We strongly believe in sharing knowledge and that’s why we create articles like this one. If you liked it, help us to continue creating content by sharing this article or [signing up in Bugfender](https://dashboard.bugfender.com/signup).