Vue.js for Angular Developers
Published: 2019-08-08 18:47:41

When writing, I focus on Angular and full-stack development, with Angular for the frontend.

Recently, I had the opportunity to write a proof-of-concept app using Vue.js to create a basic Todo app using Vue.js and the Vue CLI.

Let's take a look, go over the app, and explore Vue.js. We will also compare some of the concepts and techniques in Vue.js to those in the Angular world.

In brief, whether you are developing Angular or Vue apps, there are some basic concepts and techniques, related to architecturing or structuring your applications, that can be applied to both. For instance, the **Smart/Presentational** components is universal and applies to both worlds.

Now, the tools differ for sure. Take for example **Vuex**, which is the Vue.js library for client-side state management. You may compare that to **NGRX** or any other Angular based state management library.

The major point of this article is that, whatever framework you use to develop your apps, the concepts are yours, and you can take them with you whether you are developing in Vue or Angular.

Here’s a sneak peek at the final product we will build together today:

![](https://thepracticaldev.s3.amazonaws.com/i/a7bu8eb8eog060etn0yj.PNG)

The source code of this article is available at this GitHub [repo](https://github.com/bhaidar/todo-vue).
Let’s start coding the Todo app!

##Create Vue app
To start, make sure you install the latest version of the Vue CLI by running this command:
`yarn global add @vue/cli`

The command downloads and installs the latest bits of the Vue CLI on your machine.

After that, I will create a new Vue.js app using the Vue CLI UI instead of the command line.

Run the following command: `vue ui`

This command opens a new browser, as shown here:

![](https://thepracticaldev.s3.amazonaws.com/i/85d6525kz0xgtmotjpel.PNG)

The home page of the Vue UI allows you to manage your existing projects, create new ones, and import existing projects.

Click on the **Create** tab, and you will see something similar to this:

![](https://thepracticaldev.s3.amazonaws.com/i/ydxeflt0vmev7y3riivz.PNG)

Change the system path to the directory where you want to create a new project. In my case, I’ve chosen the path `D:\Projects`

Locate and click on the **Create a new project here** button. A new page opens as shown below:

![](https://thepracticaldev.s3.amazonaws.com/i/xjsf04mwylqaaonz55q9.PNG)

On this page you specify the following:
- **Project folder**: todo-app
- **Project manager**: yarn
- **Git repository**: On

Then, click the **Next** button to go to the page where you select a preset. 

![](https://thepracticaldev.s3.amazonaws.com/i/gbte4wletb6hctde0zbp.PNG)

You can choose the **Default preset** to create the app with default features and options. I’ve chosen the **Manual** option so that I can customize my app generation.

Locate and click on the **Next** button to go to the page where you select what features you wish to include in the app.

![](https://thepracticaldev.s3.amazonaws.com/i/9sl8m33ah1dk6gy8js1j.PNG)

For this app, I've chosen to use the following features:
- Babel
- Vuex (for state management)
- CSS Preprocessors 
- Linter/Formatter

Once done, locate and click on the **Next** button to go to the page where you have to configure the CSS preprocessors since you’ve added this feature.

![](https://thepracticaldev.s3.amazonaws.com/i/i6tcbrj55lusn39yi9sa.PNG)

In my case, I will pick the **Sass/SCSS (with node-sass)** for the CSS Preprocessor.

As for linting and formatting, I’ve decided to use **ESLint + Prettier** to combine both amazing worlds together!

Finally, I want my project to get **linted** whenever I save a file.

Click the **Create Project** button to start generating your project files.

![](https://thepracticaldev.s3.amazonaws.com/i/7vnt1vzsn5x9mucr2me2.PNG)

**NB**: Before the project file generation process starts, a prompt will appear asking if you'd like to save your current settings as a preset. This saves all the preferences and configurations for future use if you choose. For now, I will just continue without saving it as a preset.

Once the generation process ends, you get the following project created:

![](https://thepracticaldev.s3.amazonaws.com/i/p3n9z5gxcj6y6kq92zdp.PNG)

Public folder contains the `index.html` file that will be used to run your app.
Src folder contains all of your Vue components and any assets like CSS or images.
The rest are configuration files.

Now that the application is generated, let’s start building the app source code.

##Anatomy of a Vue.js app
Let’s explore the `main.ts` file and check how a Vue.js app is started:

```javascript
import Vue from 'vue'
import App from './App.vue'
import store from './store'

new Vue({
  store,
  render: h => h(App)
}).$mount('#app')
```

The file creates a new instance of the main `Vue` component passing it an object parameter containing configuration settings.

The first argument of the input parameter is the `store` object that is imported from `./store` file.

The `store` object is injected at this level so that the store object is available to all children components.

The `render()` method returns the `app.vue` root component to render for this app.

Finally, the `$mount(#app)` method is called with a DOM element so that Vue renders the root component in this DOM element inside the `index.html` page and activates the app.⁰

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

Let’s explore the store we will be using for this app.

##Vuex - State Management Simplified
At the core of [Vuex](https://vuex.vuejs.org/guide/) is the `Store` object to help with state management for your Vue apps:

The store is:
- Reactive by nature. Any change that occurs inside the store is automatically reflected inside the Vue components.
- You cannot directly mutate the store’s state. You do that by **committing a mutation** to update the store’s state via a pure-function without any side-effects.

To trigger a mutation you **dispatch an action**.

Let’s look at how the Todo app store looks like. You can check the whole store implementation on this GitHub [repo](https://github.com/bhaidar/todo-vue/blob/master/src/store.js).

The `store.js` file starts by registering `Vuex` as a plugin to the application so you can access the store’s state later on:
`Vue.use(Vuex)`

The code then creates a new instance of the `Vuex.Store()` object passing an object parameter to configure the state, mutations, actions, and getters of the store.

The state is defined as follows:

```javascript
state: {
    todos: []
  },
```

The state in this app is tracking the list of todo items.

Let's discuss a single mutation in this store:

```javascript
ADD_TODO(state, todo) {
      state.todos = [
        { body: todo, completed: false, id: generateRandom(1, 1000) },
        ...state.todos
      ]
    }
```

A mutation accepts, as input parameters, the existing `state` object in addition to the todo item to be added to the store’s state.

You can check the rest of mutations in the source code of the store referenced above.

> In [NGRX](https://ngrx.io/) - Reactive State for Angular, all the mutations are grouped inside a **Reducer**. This reducer holds all the mutations and based on the action dispatched, a single mutation is executed.

Let’s continue with the `actions` of a store. 

```javascript
addTodo({ commit }, todo) {
  commit('ADD_TODO', todo)
}
```

An action method receives the store object as an input together with the action payload. In the code, the `addTodo()` action extracts just the `commit` method from the store object. It then calls the `commit()` method, passing as parameters, the name of the mutation together with the todo item, to save in the store’s state. So, dispatching an action commits a new mutation to update the store’s state.

> Similar to NGRX an action triggers the Reducer to execute a mutation on the store.

Finally, the getters defined on the store object are convenience methods added to allow components to reactively read data from the store’s state. Whenever the store’s state changes, the components listening to the getters will be notified and updated automatically.

Here’s an example getter used in the app:

```javascript
pendingTodos: state => state.todos.filter(todo => !todo.completed)
```

`pendingTodos` getter, given a state, filters out all completed todo items and returns only those that are still pending.

> Vuex Getters are equivalent to Selectors in NGRX.

Now that we know how the Vuex Store works, let’s move on and start building the UI and functionality of the todo app.

##Building the Todo app
Let’s start at the `App.vue` root component of the app:

The component defines a main header for the home page:

```html
<header>
      <div class="navbar navbar-dark bg-dark box-shadow">
        <div class="container d-flex justify-content-between">
          <TodoBrand />
        </div>
      </div>
</header>
```

The app is using [Bootstrap 4] for the layout, and I’ve added the following two lines to add support for Bootstrap in the app.

Locate the `public\index.html` and add the following to the `<head>` of the document:

```html
 <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"
    integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css"
    integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous">
```

The head of the `App.vue` component defines a custom `TodoBrand` Vue.js component to render the brand section of the page. 

###TodoBrand component

Create a new Vue.js component under the path `src\components\TodoBrand.vue` with the following content:

{% gist https://gist.github.com/bhaidar/e2db439e2c1ce05bdbb492bfe1fda7b0 %}

This renders a `Todo` SVG icon together with the `Todo` header text.

Now you import the `TodoBrand` component inside the root `App.vue` component:

`import TodoBrand from '@/components/TodoBrand.vue'`

After that you need to inform `App.vue` about this new component by adding it to the list of components managed by `App.vue` as follows:

```javascript
components: {
   TodoBrand
}
```

The body of the `App.vue` component has 3 main sections

The header text section showing the number of pending todo items in the store’s state.

```html
<h4>
    You have
    <strong>{{ pendingTodos.length }}</strong> pending todo(s)
</h4>
```

The snippet above uses a one-way data binding to bind the `pendingTodos` computed variable defined inside the code of the component as follows:

```javascript
computed: {
    pendingTodos() {
      return this.$store.getters.pendingTodos
    }
  }
```

A computed property in Vue.js is reevaluated every time one of the fields used inside a computed property has changed.

In this example, whenever the `this.$store.getters.pendingTodos` results change, this computed variable is reevaluated.

> Doesn't this remind you of `RxJS` in Angular? The reactivity nature of both technologies?

###TodoAdd component
The `App.vue` then renders the `TodoAdd` component that, in turn, displays an input field with a button to allow the user to add a new todo item.

`<TodoAdd @add-todo="addTodo" />`

Create this component inside the `src\components` folder, and then import it to the `App.vue` component, and finally add it to the list of components managed by this root component.

The `TodoAdd` component exposes a single output event the `add-todo` event. This event is triggered by the `TodoAdd` component whenever the user adds a new todo item.

You would ask yourself why am I handling this event at the `App.vue` component rather than inside the `TodoAdd` component itself?

I am following the [Smart/Presentational](https://alligator.io/react/smart-dumb-components/) concept whereby the **Presentational** `TodoAdd` component handles the DOM events of the input field, and button, and emits a new event to the **Smart** `App.vue` component. The event handler at the `App.vue` component level handles this event by communicating directly to the store.

All presentational components have no access to the store object itself. Everything is delegated to the smart components.

Let's explore the `TodoAdd` component.

This component uses an input field with a button to allow the user to add a new todo item.

To add a new todo item, you can either enter your todo item text and hit [enter] or click the [+] button. Both ways are handled by the component.

{% gist https://gist.github.com/bhaidar/0b27019c93eefa6c4d2e0e2e2e30b35d %}

The input field uses a 2-way data-binding option via the `v-model`.

```javascript
data() {
    return {
      newTodo: ''
    }
  }
```

The `newTodo` variable is defined under the `data()` method on the `App.vue` component. 

> v-model reminds me of the 2-way data binding [(ngModel)] in Angular!

The input field also binds the `keyup.enter` event to execute the `addTodo()` method whenever the user hits [enter] inside the input field.

The `addTodo()` method is defined inside the `methods` object property of the `App.vue` component as follows:

```javascript
addTodo() {
      if (this.newTodo) {
        this.$emit('add-todo', this.newTodo)
        this.newTodo = ''
      }
}
```

The method emits the new todo item text, entered by the user, to the outside components.

The `$emit` method is defined by Vue, and is globally accessible by all Vue components to emit events to all consumers of this component.

> $emit() reminds me of the EventEmitter in Angular app!

Emitting an event involves specifying the name of the event `add-todo`, and the payload of the event.

Then back in the `App.vue`, you would listen to this event by means of binding to the event name as follows:

`<TodoAdd @add-todo="addTodo" />`

The `addTodo()` method, defined inside `App.vue` component, handles this event by dispatching a new action on the store object as follows:

```javascript
addTodo(todo) {
      this.$store.dispatch('addTodo', todo)
 }
```

You dispatch a new action on the store by calling `$store.dispatch()` method, and passing it 2 arguments:
- The name of the event to match that define in the `store.js` file.
- The payload of the event. In this case, it is the todo item text entered by the user.

The call above is handled by `Vuex` and is redirected to execute the action `addTodo` defined by the `store.js` file.

###TodoList component
The final component used inside the `App.vue` is the `TodoList` component.

```html
<TodoList
      :todos="todos"
      @change-completed="changeCompleted"
      @edit-todo="editTodo"
      @delete-todo="deleteTodo"
/>
```

This component is responsible to render a list of todo items. It accepts as input an array of todo items and exposes 3 output events:

- `change-completed` event
- `edit-todo` event
- `delete-todo` event

In addition to displaying todo items it also allows the user to:

- Mark a todo item as completed
- Edit the text of an existing todo item
- Delete an existing todo item

`App.vue` component imports this component, and adds it to the list of components it manages.

Let's explore this component together:

{% gist https://gist.github.com/bhaidar/2942941cbf56a11c88848afc9809a073 %}

The component makes use of the `TodoItem` component to render every single todo item. We will explore this component in depth shortly.

The component uses the `v-for` directive to loop over the todo records, and render a single instance of `TodoItem` per todo item. 

It is very important to specify the `:key="item.id"` for performance enhancement reasons. 

> `v-for` directive is equivalent to `*ngFor` directive in Angular.

The component handles the events exposed by `TodoItem` component and then re-emits the same events to the parent or outer component, the `App.vue` root component in this case.

The events are handled by means of 3 methods defined inside the `methods` object property on the `TodoList` component.

###TodoItem component
Now let’s explore the final component in this app, the `TodoItem` component.

{% gist https://gist.github.com/bhaidar/5a5c3082305d3a7a98d5777279432938 %}

For each and every todo item, the component renders the following:
- A checkbox field to mark the todo item as completed (on/off)
- An input field to display the todo item text and allow the user to edit the text
- A button to allow the user to delete the todo item

The text of todo item is coming from the input property `todo` defined by the `TodoItem` component inside the `props` object property.

> `props` in Vue reminds me of `@Input()` in Angular

The component subscribes to the `change` event of the checkbox field by executing the `changeCompleted()` event handler method, defined inside the `methods` object property of the `TodoItem` component. The event handler emits the `change-completed` event to the outer components to signal a change in the `completed` state of a specific todo item.

> `$emit()` in Vue reminds me of `@Output()` in Angular

The component subscribes to the `change` event of the input field by executing the `editTodo()` event handler method defined inside the `methods` object property of the `TodoItem` component. The event handler emits the `edit-todo` event to the outer components to signal an edit in the text of the todo item. It also provides a payload for this change to be eventually reflected on the store’ stat.

The component subscribes to the `click.prevent` event of the delete button by executing the `deleteTodo()` event handler method defined inside the `methods` object property of the `TodoItem` component. The event handler prompts the user for a confirmation of deletion, before emitting the `delete-todo` event to the outer components, to signal deletion of the todo item, and eventually reflect that to the store’s state.

That's it! If you visit the `App.vue` root component again, you will understand how the component is composed of the `TodoBrand`, `TodoAdd`, `TodoList`, and `TodoItem` components.

Finally, to serve the application, run the following command:
`yarn serve`

Once the app starts, you can access it by navigating your browser to `http://localhost:8080`, and playing with the todo app.

##Conclusion
I am pretty sure you would agree that the concepts in both Vue and Angular are close. Only the details of how to use this or that feature differ, and you can learn them in no time.

One more feature that I've touched on in this article is the [Vue Router](https://router.vuejs.org/) module that allows you to define routes in your application. Once again, it resembles that of the Angular Router library.

The Vue.js framework has an extensive documentation website that’s easy to follow, and is always up to date. You can check it [here](https://vuejs.org/v2/guide/).


This post was written by [Bilal Haidar](https://www.bhaidar.dev/), a mentor with [This Dot](https://thisdot.co/).

*You can follow him on Twitter at [@bhaidar](https://twitter.com/bhaidar).*

*Need JavaScript consulting, mentoring, or training help? Check out our list of services at [This Dot Labs](https://thisdot.co).*