Vue.js is gaining popularity for all the right reasons, and the future looks bright for Vue and the combination of Progressive Web Applications. Ionic is a web framework at the forefront of combining mobile-first UX and although it’s currently powered by Angular 5.x, the team’s new Stencil compiler allows Vue.js to use the same Web Components with Ionic 4.
Ionic 4 is currently in alpha and should not be used in production, but nevertheless, this is a great thought experiment and dives deep into the benefits of Stencil and what Web Components mean for framework agnostic UI components.
To get started, create a new Vue project with the Vue CLI:
# Install the Vue CLI
$ npm install vue-cli
# Create a new Vue project
$ vue init webpack-simple vue-ionic
# Change directory
$ cd vue-ionic
# Add vue-router and axios
$ npm install vue-router axios
# Run development server
$ npm run dev
We can make a local REST API with json-server
which allows us to easily GET and POST todos to our server. Install this globally on your machine if you haven’t got it already:
$ npm install json-server -g
The server can be started with a JSON serialized database. Create a file named db.json
inside of the root of your project:
db.json
```json { “todos”: [ { “id”: 1, “name”: “Make awesome applications” }, { “id”: 2, “name”: “Play squash” }, { “id”: 3, “name”: “Deadlift” }, { “id”: 4, “name”: “Squat” } ] } ```
Start the API by running the following in the terminal:
$ json-server db.json --watch --port 3001
Now that we have an API up and running, let’s add Ionic!
To add an alpha version of Ionic inside of our project, adding the following script to our index.html file:
<script src="https://unpkg.com/@ionic/core@0.0.2-30/dist/ionic.js"></script>
You can find the current version of Ionic core here: https://www.npmjs.com/package/@ionic/core
At the same time, ensure you’ve got the appropriate responsive meta tag:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
We can then set up two routes that allow us to either view todo items or add todo items:
import Vue from 'vue'
import VueRouter from 'vue-router';
import TodoList from './components/TodoList';
import AddTodoItem from './components/AddTodoItem';
Vue.use(VueRouter);
const routes = [
{ path: '', redirect: '/todos'},
{ path: '/todos', component: TodoList },
{ path: '/todos/add', component: AddTodoItem}
]
export default new VueRouter({ routes })
Afterward, add the router configuration to our main Vue instance inside of main.js
:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
new Vue({
el: '#app',
router,
render: h => h(App)
})
As Ionic 4.x is built using Web Components, we’ll need to tell Vue that the ion-
components aren’t Vue components. Inside of main.js
, add the following configuration object that ignores all Ionic elements:
Vue.config.ignoredElements = [/^ion-/]
Inside of App.vue
we can now add our <router-view>
and enclose this in an <ion-app>
component. This is used to enclose all of our Ionic components:
<template>
<ion-app>
<router-view></router-view>
</ion-app>
</template>
To create the todo list page that we registered inside of router.js
, create a file named TodoList.vue
inside of the src/components
folder.
Inside of our created
hook, we’re capturing the todos
from our API and assigning them to the todos
array.
import axios from 'axios';
export default {
data() {
return {
todos: []
}
},
methods: {
addTodo() {
this.$router.push({path: '/todos/add'})
}
},
created() {
axios.get('http://localhost:3001/todos')
.then(res => this.todos = res.data)
}
}
We can then add a template which will certainly look similar to anyone that’s used Ionic in the past:
<template>
<ion-page>
<ion-header>
<ion-toolbar class="toolbar-md-primary">
<ion-title>TodoList</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="content">
<ion-list>
<ion-item v-for="todo in todos" :key="todo.id">
{{todo.name}}
</ion-item>
</ion-list>
<ion-fab-button class="todo-fab" @click="addTodo">
<ion-icon name="add"></ion-icon>
</ion-fab-button>
</ion-content>
</ion-page>
</template>
We wrap our component inside of an ion-page
element. This then allows us to define a header and toolbar which gives us the ability to display a navigation bar.
Next, we can display the list inside of an ion-content
element and iterate over each item inside of our todos
array as an ion-item
.
To style our fab button and add some padding. We’ll be using both classes across both of our components so let’s add a style.css
file and the appropriate classes:
.todo-fab {
position: fixed;
bottom: 25px;
right: 15px;
font-size: 30px;
}
.content {
padding: 10px 10px 10px 0px
}
When the user clicks the FAB button, they’ll be navigated to the Add Todo page. Let’s create that at components/AddTodoItem.vue
:
<template>
<ion-page>
<ion-header class="toolbar-md-primary">
<ion-toolbar>
<ion-title>Add Item</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="content">
<ion-item>
<ion-input :value="name" ref="newTodoItem" @input="updateTodoName" placeholder="Todo Name"></ion-input>
</ion-item>
<ion-fab-button class="todo-fab" @click="addTodo">
<ion-icon name="checkmark"></ion-icon>
</ion-fab-button>
</ion-content>
</ion-page>
</template>
Our markup looks quite similar, but this time we’re using an ion-input
. To get the value
of the new todo item we’re using a ref
and an input
event.
import axios from 'axios';
export default {
data() {
return {
name: ''
}
},
methods: {
addTodo() {
const newTodo = { name: this.name }
axios.post('http://localhost:3001/todos', newTodo)
.then(res => {
this.$router.push({path: '/todos'})
})
},
updateTodoName() {
this.name = this.$refs.newTodoItem.value
}
}
}
The code for this page is quite similar too, we’re adding a new Todo item to our API using axios whenever someone clicks the FAB button.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.