<div id="app">

  <form id="input-container" @submit.prevent="add(employee)">
    <input placeholder="name" type="text" v-model="employee.name" required ref="firstInput">
    <input placeholder="age" type="number" v-model="employee.age" required>
    <input placeholder="email" type="email" v-model="employee.email" required>
    <button type="submit" title="Add employee">+</button>
  </form>

  <ul v-if="employees.length">
    <li v-for="(employee, index) in employees" class="employee" :key="employee.name" v-if="employee">
      <button @click="remove(employee.id, index)" id="remove" title="Remove employee">⨯</button>
      <span>{{employee.name}} • {{employee.age}} • {{employee.email}}</span>
    </li>
  </ul>

  <p v-else>No contacts found.</p>

</div>
#input-container {
  display: grid;
  grid-template-columns: 1fr 0.5fr 2fr 2rem;
  height: 2rem;

  border: 2px solid #0ea5e9;
  border-radius: 0.4rem;

  padding: 0.1rem;
}

input {
  border: none;
  color: #0ea5e9;
  background: none;

  padding: 0 1rem;
  outline: none !important;
}

input:not(:nth-child(3)) {
  border-right: 2px solid #0ea5e9;
}

#input-container button {
  background: #0ea5e9;
  border: none;
  color: #fff;

  font-size: 1.2rem;
  font-weight: 900;

  cursor: pointer;
  border-radius: 0.1rem;
}

button:hover {
  filter: brightness(1.01);
}

button:active {
  filter: brightness(0.98);
}

p {
  font-family: sans-serif;
}

ul {
  list-style: none;
}

#remove {
  background: none;
  border: none;

  cursor: pointer;
  background: #f5f5f4;
  aspect-ratio: 1;
  border-radius: 50%;
  margin-right: 1rem;
}

.employee {
  font-family: sans-serif;
}
//prefixes of implementation that we want to test
window.indexedDB =
  window.indexedDB ||
  window.mozIndexedDB ||
  window.webkitIndexedDB ||
  window.msIndexedDB;

//prefixes of window.IDB objects
window.IDBTransaction =
  window.IDBTransaction ||
  window.webkitIDBTransaction ||
  window.msIDBTransaction;
window.IDBKeyRange =
  window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;

if (!window.indexedDB) {
  window.alert("Your browser doesn't support a stable version of IndexedDB.");
}

const employeeData = [];
var db;
var request = window.indexedDB.open("contacts", 4);

request.onerror = function (event) {
  console.log("error: ");
};

request.onsuccess = function (event) {
  db = request.result;
  console.log("success: " + db);
};

request.onupgradeneeded = function (event) {
  var db = event.target.result;
  var objectStore = db.createObjectStore("employee", { keyPath: "id" });

  for (var i in employeeData) {
    objectStore.add(employeeData[i]);
  }
};

new Vue({
  el: "#app",
  data() {
    return {
      employee: {
        id: null,
        name: null,
        age: null,
        email: null
      },
      employees: [],
      retryCount: 0
    };
  },
  mounted() {
    this.readAll();
  },

  methods: {
    add(employee) {
      var vm = this;
      let request = new Promise((resolve, reject) => {
        var request = db
          .transaction(["employee"], "readwrite")
          .objectStore("employee")
          .add({
            id: employee.id != null ? employee.id : vm.employees.length++,
            name: employee.name,
            age: employee.age,
            email: employee.email
          });
        request.onsuccess = function (event) {
          vm.employees.push({
            edit: false,
            id: employee.id != null ? vm.employee.id : vm.employees.length++,
            name: employee.name,
            age: employee.age,
            email: employee.email
          });

          employee.name = null;
          employee.age = null;
          employee.email = null;
          this.$refs.firstInput.focus();
        };
        request.onerror = function (event) {
          alert("Unable to add data ");
        };
      });
    },
    readAll() {
      var vm = this;
      try {
        vm.employees = [];
        var objectStore = db.transaction("employee").objectStore("employee");
        if (objectStore) {
          objectStore.openCursor().onsuccess = function (event) {
            var cursor = event.target.result;

            if (cursor) {
              if (vm.employees) {
                vm.employees.push({
                  edit: false,
                  id: cursor.key,
                  name: cursor.value.name,
                  age: cursor.value.age,
                  email: cursor.value.email
                });
              }
              cursor.continue();
            }
          };
        }
      } catch (e) {
        vm.retryDisp();
      }
    },
    remove(id, index) {
      var vm = this;
      var request = db
        .transaction(["employee"], "readwrite")
        .objectStore("employee")
        .delete(id);
      vm.employees.splice(index, 1);
    },
    retryDisp() {
      var vm = this;
      if (++vm.retryCount > 5) {
        console.log("Cannot open the database after 5 retries");
        vm.readAll();
      }
      setTimeout(function () {
        vm.readAll();
      }, 100);
    }
  }
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js