> For the complete documentation index, see [llms.txt](https://devworkshops.gitbook.io/masteringvuejs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://devworkshops.gitbook.io/masteringvuejs/getting-started/your-first-app.md).

# Your First App

### Getting started

Create a new file named **main.js** and move the contents of the script block into the new file:

{% code title="	" %}

```javascript
var app = new Vue({
  el: "#app",
  data: {
    title: "Hello, World!"
  }
});
```

{% endcode %}

Within **index.html**, remove the script block (if you haven't already) and then add a reference to the newly created **main.js** file:

{% code title="index.html" %}

```markup
...
<script src="main.js"></script>
...
```

{% endcode %}

The above reference should appear just before the closing `body` tag.&#x20;

Next, inside the `head` element, add a reference to Bootstrap from the CDN. This is step is not mandatory but it will make the UI look way better just out of the box.

{% code title="index.html" %}

```markup
...
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
...
```

{% endcode %}

Within **index.html**, replace the existing `div` element with an updated version as follows:

{% code title="index.html" %}

```markup
...
<div id="app" class="container">
    <h1>{{ title }}</h1>
    <ul class="list-group mb-2">
        <li class="list-group-item">
            <div class="form-check">
                <input class="form-check-input" type="checkbox" id="todo1" />
                <label class="form-check-label" for="todo1">Do this thing.</label>
            </div>
        </li>
        <li class="list-group-item">
            <div class="form-check">
                <input class="form-check-input" type="checkbox" id="todo2" /> 
                <label class="form-check-label" for="todo2">Do more things.</label>
            </div>
        </li>
        <li class="list-group-item">
            <div class="form-check">
                <input class="form-check-input" type="checkbox" id="todo3" />
                <label class="form-check-label done" for="todo3">This thing is done.</label>
            </div>
        </li>
    </ul>
</div>
...
```

{% endcode %}

Create a new file named **main.css** and add the following style. This will be used to add the strike through for done tasks.

{% code title="main.css" %}

```css
.done {
    text-decoration: line-through;
}
```

{% endcode %}

Save all changes and view **index.html** in your browser. Your app should display the following:

![](/files/-Lfs4Gve4HO-QBXvewk8)

### Store and display todo items

Store the todo items data in the root Vue instances local state. The local state is stored within the data property. Add the new todos array into the data property in the **main.js** as follows:

{% code title="main.js" %}

```javascript
...
todos: [
    { id: 1, title: "Do this thing.", done: false, created: new Date(2019,1,1) },
    { id: 2, title: "Do another thing.", done: false, created: new Date(2019,3,1) },
    { id: 3, title: "Do many, many things!", done: false, created: new Date() },
    { id: 4, title: "This thing is done.", done: true, created: new Date() }
],
...
```

{% endcode %}

Update the template. First remove the existing static todo items (`<li>`) then add a dynamic list item to display the todo items:

{% code title="index.html" %}

```markup
...
<li class="list-group-item" v-for="(todo, index) in todos" :key="todo.id">
  <div class="form-check">
    <input class="form-check-input" type="checkbox" :id="'todo' + index" v-model="todo.done" />
    <label class="form-check-label" :for="'todo' + index" :class="{ done: todo.done }">{{ todo.title }}</label>
  </div>
</li>
...
```

{% endcode %}

Save all changes and verify that the todo items display correctly.

### Create new todo items

Next, you will add support for creating todo items. First add two new properties to local state (within the data property):

{% code title="main.js" %}

```javascript
...
nextId: 5,
newTodoTitle: null
...
```

{% endcode %}

Then, to support adding new todo items, create an `addTodo` method within the root instance:

{% code title="main.js" %}

```javascript
...
methods: {
  addTodo() {
    this.todos.push({
      id: this.nextId++,
      title: this.newTodoTitle,
      created: new Date(),
      done: false
    });
    
    this.newTodoTitle = ''
  }
}
...
```

{% endcode %}

Finally, update the template to include the form to invoke the new `addTodo` method:

{% code title="index.html" %}

```markup
...
<form class="mb-2" v-on:submit.prevent="addTodo">
  <input class="form-control" placeholder="Add todo..." v-model="newTodoTitle" />
</form>
...
```

{% endcode %}

Save all changes and verify that you can now add new todo items.

### Filter todo items

Next you will add support for filtering todo items. The supported filters are **All**, **Todo**, and **Done**. Add the list of valid filters and active filter to local state (within the data property) as follows:

{% code title="main.js" %}

```javascript
...
filters: ["All", "Todo", "Done"],
activeFilter: 'All',
...
```

{% endcode %}

In order to filter the todo items based on the active filter you will use a computed property. Update **main.js** to include a new `filteredTodos` computed property. Keep in mind that the computed section is in the same level as the methods and data, not inside of them.

{% code title="main.js" %}

```javascript
...
computed: {
  filteredTodos() {
    if (this.activeFilter === "All") {
      return this.todos;
    }

    if (this.activeFilter === "Todo") {
      return this.todos.filter(t => !t.done);
    }

    if (this.activeFilter === "Done") {
      return this.todos.filter(t => t.done);
    }
  }
}
...
```

{% endcode %}

Next, include the filters on top of the list (`<ul>`). Update **index.html** as follows:

{% code title="index.html" %}

```markup
...
<nav class="nav nav-pills mb-2">
  <a class="nav-link" href="#" 
      v-for="filter in filters" 
      :key="filter" 
      :class="{ active: filter === activeFilter }" 
      @click="activeFilter = filter">
  {{ filter }}
  </a>
</nav>
...
```

{% endcode %}

Finally, update the template to use the `filteredTodos` computed property rather than access the todo items directly:

{% code title="index.html" %}

```markup
...
<li class="list-group-item" v-for="(todo, index) in filteredTodos" :key="todo.id">
...
```

{% endcode %}

Save all changes and verify that the todo items are filtered correctly.

### Display number of remaining todo items

The last step is to update the template to display the correct number of remaining items. You can add it after the form tag.&#x20;

{% code title="index.html" %}

```markup
...
<div class="alert alert-danger" v-if="todos.filter(t => !t.done).length>10">
You've got a long day ahead of you!!!
</div>
<div class="alert alert-secondary" v-else-if="todos.filter(t => !t.done).length>0">
{{ todos.filter(t => !t.done).length }} item(s) remaining.
</div>
<div class="alert alert-success" v-else>
Hooray!!! You're all done, go to the beach!!!
</div>
...
```

{% endcode %}

Save the change and verify that number of remaining todo items is correct, and updates when items are added or marked as done.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://devworkshops.gitbook.io/masteringvuejs/getting-started/your-first-app.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
