This post will explain a caveat of the IndexedDB API that I have encountered and my work around.
Part 1 of the IndexedDB posts explains that it’s possible to store objects using a keyPath and autoIncrement. The documentation states that the key will be stored in object[keyPath] if it doesn’t exists already. This is not true. Examine the following code
// open a transaction and access the object store
var objStore = ...; // object store has keyPath and autoIncrement
// obj = object with keyPath undefined
var obj = ...;
var request = objStore.add(obj);
request.onsuccess = function(event) {
console.log(obj.keyPath);
};
This will add an object and print the value of the objects keyPath. When running the code, it prints undefined. This is against what the documentation states, but there is an easy work around. It is this utility function.
function addObject(objectStore, object) {
var request = objectStore.add(object);
request.onsuccess = function(event) {
var keyPath = event.target.source.keyPath;
object[keyPath] = this.result;
};
}
The function encapsulates the scope of the object, and updates the keyPath value with the key. The keyPath value is stored in event.target.source.keyPath, and the new key is the result. With this function, the code changes only slightly but works as expected.
// open a transaction and access the object store
var objStore = ...; // object store has keyPath and autoIncrement
// obj = object with keyPath undefined
var obj = ...;
addObject(objStore, obj);
After the code is run and the result is received, the object will be updated with the correct key. They only drawback to this workaround is that it limits the users from being able to execute code on the request.onsuccess call back. The function could be modified to receive an optional callback as a parameter to remedy this.
The demo of the code using this functionality is here. It behaves the same way but the code is a little clearer and more straightforward. Source Code