Language: EN

api-rest-con-esp8266-axios-vuejs-y-vuetify

How to make an Api Rest with ESP8266 or ESP32, Axios, VueJs and Vuetify

We continue with our tutorials section of the ESP8266 and ESP32 seeing how to integrate an application that combines VueJs, Vuetify, Axios and communicates with the ESP8266 through a Rest API.

We will refer to the ESP8266, but the same code is compatible for the ESP32, adjusting the name of the libraries. At the end you have the code for both the ESP8266 and the ESP32.

In the previous entry of this series, we were integrating an application in VueJs, which used the Axios library to communicate through a Rest API with the ESP8266 acting as a backend.

Our application could be a good example of architecture but… let’s admit that it was ugly as sin. But this is about to change! To do this, we are going to incorporate Vuetify into our cocktail, which we already saw in this post.

esp8266-vue-vuetify-axios-resultado

The goal is to achieve functionality similar to the previous one, that is, a demo that shows how to perform the different actions through the Rest API, but with this more modern and suitable aesthetic.

Looks better, right? Well, let’s get to work. The backend code, that is, the ESP8266, is identical to the last two entries. So, again, I avoid copying it again and refer you to the previous entries or the code on Github.

What is going to change is the served web page.

The index.html file becomes

<!DOCTYPE html>
<html>
  <head>
    <title>ESP8266 Vuetify + Axios</title>
    <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- From CDN -->
    <!--<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet">-->
    <!--<link href="https://cdn.jsdelivr.net/npm/vuetify@1.5.16/dist/vuetify.min.css" rel="stylesheet">-->

    <link href="./vendor/google-fonts.css" rel="stylesheet">
    <link href="./vendor/vuetify.min.css" rel="stylesheet">
   </head>
<body>
    <div id="app">
      <v-app id="inspire">
        <v-container style="max-width: 600px">
          <v-form>
            <v-container>
              <v-layout row>
                <v-flex xs12 sm6 md3>
                  <v-btn color="info" @click="getAll">Get All</v-btn>
                </v-flex>
              </v-layout>

              <v-layout row>
                <v-flex xs12 sm6 md3>
                  <v-btn color="info" @click="getById">Get</v-btn>
                </v-flex>

                <v-flex xs12 sm6 md3>
                  <v-text-field v-model.number="getId" label="Id" solo type="number"></v-text-field>
                </v-flex>
              </v-layout>

              <v-layout row>
                <v-flex xs12 sm6 md3>
                  <v-btn color="info" @click="updateById">Update</v-btn>
                </v-flex>

                <v-flex xs12 sm6 md3>
                  <v-text-field v-model.number="updateId" label="Id" solo type="number"></v-text-field>
                </v-flex>

                <v-flex xs12 sm6 md3>
                  <v-text-field v-model="updateText" label="Text" solo></v-text-field>
                </v-flex>
              </v-layout>
            </v-container>
          </v-form>

          <v-divider class="mb-3"></v-divider>

          <v-text-field v-model="newItem" label="Add new item" solo @keydown.enter="create">
            <v-fade-transition slot="append">
              <v-icon v-if="newItem" @click="create">add_circle</v-icon>
            </v-fade-transition>
          </v-text-field>

          <v-card>
            <v-toolbar color="cyan" dark>
              <v-toolbar-title>Total: {{ items.length }}</v-toolbar-title>
            </v-toolbar>

            <v-fade-transition class="py-0" group tag="v-list">
              <template v-for="(item, i) in items">
                <v-divider v-if="i !== 0" :key="`${i}-divider`" ></v-divider>

                <v-list-tile :key="`${i}-${item.text}`">
                  <v-list-tile-action>
                    <v-list-tile-title v-text="item.id"></v-list-tile-title>
                  </v-list-tile-action>

                  <v-list-tile-action>
                    <v-list-tile-content>

                      <v-list-tile-title v-text="item.text"></v-list-tile-title>
                    </v-list-tile-content>
                  </v-list-tile-action>

                  <v-spacer></v-spacer>
                  <div>
                    <v-btn color="error" v-model="item" @click="remove(item)">Delete</v-btn>
                  </div>
                </v-list-tile>
              </template>
            </v-fade-transition>

            <v-snackbar v-model="snackbar" :bottom="true" :timeout="timeout">
              {{ text }}
              <v-btn color="pink" flat @click="snackbar = false">
                Close
              </v-btn>
            </v-snackbar>
          </v-card>
        </v-container>
      </v-app>
    </div>

  <!-- From CDN -->
  <!--<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.min.js"></script>-->
  <!--<script src="https://cdn.jsdelivr.net/npm/vuetify@1.5.16/dist/vuetify.min.js"></script>-->
  <!--<script src="https://cdn.jsdelivr.net/npm/axios@0.18.0/dist/axios.min.js"></script>-->

  <script type="text/javascript" src="./vendor/vue.min.js"></script>
  <script type="text/javascript" src="./vendor/vuetify.min.js"></script>
  <script type="text/javascript" src="./vendor/axios.min.js"></script>
    
  <script type="text/javascript" src="./js/API.js"></script>
  <script type="text/javascript" src="./js/app.js"></script>
   </body>
</html>

The JavaScript file of the page must also be modified to adapt to the new Vuetify Framework, as follows.

new Vue({
  el: '#app',
  
  data: () => ({
    items: [
      {
        id: 0,
        done: false,
        text: 'Init 0'
      }
    ],
    
    newItem: null,
    getId: null,
    updateId: null,
    updateText: null,
    
    snackbar: false,
    timeout: 1500,
    text: '',
    
    lastId : 0,
  }),
  
  computed: {
  },
  
  methods: {
    create () {
      lastId = Math.max(...this.items.map(d => d.id));
      this.items.push({
        id: ++this.lastId,
        done: false,
        text: this.newItem
      })
      
      API_post(this.newItem)
      this.newItem = null
    },
    getAll() {
      this.text = "Getting all"
      this.snackbar = true
      
      API_getAll()
      
      lastId = Math.max(...this.items.map(d => d.id));
      this.items.push({id: ++this.lastId, text: 'Loaded all '})
      this.items.push({id: ++this.lastId, text: 'Loaded all '})
    },
    getById() {
      if(this.getId == null) return;
      if(((typeof this.items.find(x => x.id === this.getId) !== 'undefined'))) return;
      
      this.text = "Getting by Id " + this.getId
      this.snackbar = true
      
      API_get(this.getId)
      
      this.items.push({id: this.getId, text: 'Loaded by Id'})
    },
    updateById(id) {
      if(this.updateId == null || this.updateId == null) return;
      
      this.text = "Updating " + this.updateId + " with " + this.updateText
      this.snackbar = true
      
      API_put(this.updateId, this.updateText)
      
      this.items.find(x => x.id === this.updateId).text = this.updateText
    },
    remove(item) {
      this.text = "Deleting " + item.id
      this.snackbar = true
      
      API_delete(item.id)
      
      this.items.splice(this.items.indexOf(item), 1)
    }
  }
})

Result

We upload our content to the SPIFFS as usual, and press the different buttons to check that everything works correctly in the browser’s development console.

esp8266-vuejs-axios-console

As well as that they arrive correctly at the ESP8266 as a backend, through the serial port terminal.

esp8266-vuejs-axios-serial

And we have finished this series of tutorials! We have integrated a Rest API, Json, Axios, Vue, and Vuetify in a functional and beautiful demo app. You can be proud! (pat on the back)

So, are we done? Not at all. In the next three entries, we will see how to create an API for the ESP8266 that allows reading analog/digital inputs and performing actions, through Websocket, also using Vue on the frontend. See you soon!

Download the code

All the code from this post is available for download on Github.

github-full

Version for the ESP8266: https://github.com/luisllamasbinaburo/ESP8266-Examples

Version for the ESP32: https://github.com/luisllamasbinaburo/ESP32-Examples