In this, I’ll show you how to vue2 composition API.
Let us do a small example todo app with Vue composition API
Vue 3 come up with Composition API, in Vue 2, we use The Options API, where we use uses options like data
, methods
, and mounted
. With the Composition API, we have a setup
hook in which we write our reactive code and functions.
We can re-use the same functions in between components using Composition API, and save a lot of time.
Demo: https://vue-composition-api-simple-todo.pages.dev/
Setup and Installation
We can install vueCLI and create a new project using vue create vue-composition-api-simple-todo
. Please refer to my previous post in case you missed it.
Once we create our Vue project open the code base and let’s start with installing @vue/composition-api
Install dependencies
npm i @vue/composition-api --save
Let us take the same HTML from my last past, simple vue todo app Here you can read it if you miss
Let us import @vue/composition-api and use it main.js
import CompositionApi from '@vue/composition-api'
Vue.use(CompositionApi)
Start with coding
Full code of main.js looks like below
import Vue from 'vue'
import App from './App.vue'
import CompositionApi from '@vue/composition-api'
Vue.config.productionTip = false
Vue.use(CompositionApi)
new Vue({
render: h => h(App),
}).$mount('#app')
Let us create a new folder for composable functions
We can define Todos list in composable function like below
import { reactive } from "@vue/composition-api";
function useTodoList() {
let state = reactive({
newTodo: "",
todos: [
{
id: 1,
title: "Buy groceries for next week",
completed: false,
},
{
id: 2,
title: "Pay credit card bill ",
completed: false,
},
],
});
return {
state,
};
}
export default useTodoList
We use the same date, in composition functions, we will define state using Reactivity API, e.g.
ref()
and reactive()
, that allows us to directly create reactive state, computed state, and watchers.
In this example, we use reactive
to define the state and now we can use todos
inside out template.
in components/TodoList.vue
we can import composable function
import useTodoList from "@/composable/useTodoList";
export default {
setup() {
const { state} = useTodoList();
return {
state,
};
},
};
and we can use it in the template
<tbody>
<tr
v-for="(todo, idx) in state.todos"
:key="todo.id"
:class="todo.completed && 'stricked'"
>
<th scope="row">{{ idx + 1 }}</th>
.....
</tr>
</tbody>
Start the app
If we run the application we can see a list of todos 🙂
Let’s add more functionality like addtodo
toggleCompleted
and removeItem
in composable/useTodoList.js
.
The final code looks like below
import { reactive } from "@vue/composition-api";
function useTodoList() {
......
function addToDo(e) {
console.log("state.newTodo", state, state.newTodo);
e.preventDefault();
state.todos.push({
id: state.todos.length + 1,
title: state.newTodo,
completed: false,
});
state.newTodo = "";
}
function toggleCompleted(item) {
item.completed = !item.completed;
}
function removeItem(item) {
state.todos = state.todos.filter((newItem) => newItem.id !== item.id);
}
return {
state,
addToDo,
toggleCompleted,
removeItem,
};
}
export default useTodoList
Let us import addtodo
toggleCompleted
and removeItem
in components/TodoList.vue
<script>
import useTodoList from "@/composable/useTodoList";
export default {
setup() {
const { state, addToDo, toggleCompleted, removeItem } = useTodoList();
return {
state,
addToDo,
toggleCompleted,
removeItem,
};
},
};
</script>
How we can use it in the template?
....
<div class="col-12">
<button
type="button"
class="btn btn-primary"
@click="addToDo"
>
Save
</button>
</div>
.......
<tbody>
<tr
v-for="(todo, idx) in state.todos"
:key="todo.id"
:class="todo.completed && 'stricked'"
>
<th scope="row">{{ idx + 1 }}</th>
<td>{{ todo.title }}</td>
<td>
{{ todo.completed ? "Completed" : "In progress" }}
</td>
<td>
<button
type="submit"
class="btn btn-danger"
@click="removeItem(todo)"
>
Delete
</button>
<button
type="submit"
class="btn btn-success ms-1"
@click="toggleCompleted(todo)"
>
{{ todo.completed ? "Re-open" : "Complete" }}
</button>
</td>
</tr>
</tbody>
....
Once we run the server, we can see add toggle and remove is working
Getting everything working
components/TodoList.vue
<template>
<div class="hello">
<section class="vh-100" style="background-color: #eee">
<div class="container py-5 h-100">
<div class="row d-flex justify-content-center align-items-center h-100">
<div class="col col-lg-9 col-xl-7">
<div class="card rounded-3">
<div class="card-body p-4">
<h4 class="text-center my-3 pb-3">
Simple Vue 2 with composition-api To Do App
</h4>
<form
class="row row-cols-lg-auto g-3 justify-content-center align-items-center mb-4 pb-2"
@submit.prevent="addToDo"
>
<div class="col-12">
<div class="form-outline">
<input
type="text"
id="form1"
v-model="state.newTodo"
class="form-control"
placeholder="Enter a task here"
/>
</div>
</div>
<div class="col-12">
<button
type="button"
class="btn btn-primary"
@click="addToDo"
>
Save
</button>
</div>
<div class="col-12">
<button type="submit" class="btn btn-warning">
Get tasks
</button>
</div>
</form>
<table class="table mb-4">
<thead>
<tr>
<th scope="col">No.</th>
<th scope="col">Todo item</th>
<th scope="col">Status</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
<tr
v-for="(todo, idx) in state.todos"
:key="todo.id"
:class="todo.completed && 'stricked'"
>
<th scope="row">{{ idx + 1 }}</th>
<td>{{ todo.title }}</td>
<td>
{{ todo.completed ? "Completed" : "In progress" }}
</td>
<td>
<button
type="submit"
class="btn btn-danger"
@click="removeItem(todo)"
>
Delete
</button>
<button
type="submit"
class="btn btn-success ms-1"
@click="toggleCompleted(todo)"
>
{{ todo.completed ? "Re-open" : "Complete" }}
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
</template>
<script>
import useTodoList from "@/composable/useTodoList";
export default {
setup() {
const { state, addToDo, toggleCompleted, removeItem } = useTodoList();
return {
state,
addToDo,
toggleCompleted,
removeItem,
};
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #37dd92;
}
.stricked {
text-decoration: line-through;
}
</style>
composable/useTodoList.js
import { reactive } from "@vue/composition-api";
function useTodoList() {
let state = reactive({
newTodo: "",
todos: [
{
id: 1,
title: "Buy groceries for next week",
completed: false,
},
{
id: 2,
title: "Pay credit card bill ",
completed: false,
},
],
});
function addToDo(e) {
console.log("state.newTodo", state, state.newTodo);
e.preventDefault();
state.todos.push({
id: state.todos.length + 1,
title: state.newTodo,
completed: false,
});
state.newTodo = "";
}
function toggleCompleted(item) {
item.completed = !item.completed;
}
function removeItem(item) {
state.todos = state.todos.filter((newItem) => newItem.id !== item.id);
}
return {
state,
addToDo,
toggleCompleted,
removeItem,
};
}
export default useTodoList
That’s it Yey !!!
Repo: https://github.com/shabeeb/vue-composition-api-simple-todo
Demo: https://vue-composition-api-simple-todo.pages.dev/
Thank you for reading and Happy coding 🙂
1,388 total views, 1 views today
Leave a Reply