I have an array as my keypath using indexedDB and it works fine with Chrome and Firefox, but when I try to add/put using IE it gives me a DataError.
var request = window.indexedDB.open("MyTestDatabase");
request.onsuccess = function(event) {
var database = event.target.result;
var transaction = database.transaction(["document"], "readwrite");
var objectStore = transaction.objectStore("document");
var request = objectStore.put({title: 'MyDoc', version: 0});
request.onsuccess = function() {
console.log('document added');
};
request.error = function(error) {
console.log(JSON.stringify(error));
};
transaction.oncomplete = function() {
console.log('transaction complete');
};
transaction.onerror = function(error) {
console.log(JSON.stringify(error));
};
};
request.onupgradeneeded = function(event) {
event.target.result.createObjectStore("document", {keyPath: ['title', 'version']});
};
Error Screenshot:
How can I keep my double keyPath and get it to work with IE?
The only way to get around this at the moment is to create a string out of the array and use it at the key as Kyaw mentioned.
request.onupgradeneeded = function(event) {
event.target.result.createObjectStore("document", {keyPath: ['id']});
};
The id in the example would now have to be a concatenated string containing the title and version. Some like: MyDoc_0. You'd still store the title and version fields though so you can easily access them without have to split the id string.
Related
I am using javascript to do this.
I want to add data to the database (indexedDB). The data will be coming from the webservice as json and I am looping through it and adding it to an objectStore with a keyPath.
When I look at the data from the webservice, I have an array of 186 objects but when I read the data from indexedDB, I have 151. When I went to check the database to see if the data was there, it wasn't... So something must be going on with my add function.
Here is my code:
Opening a database with an objectStore:
let db;
let request = window.indexedDB.open("WHS", 4);
request.onerror = function(event) {
console.log(event.target.errorCode);
};
request.onsuccess = function(event) {
db = event.target.result;
};
request.onupgradeneeded = function(event) {
let db = event.target.result;
let palletStore = db.createObjectStore("pallets", { keyPath: "palletno" });
};
Adding data after passing it to my function:
function addPalletsToIDB(pallets) {
let transaction = db.transaction(["pallets"], "readwrite");
let objectStore = transaction.objectStore("pallets");
$.each(pallets, function(i, pallet) {
let request = objectStore.put(pallet);
})
request.onsuccess = function(event) {
console.log('Added pallets : ', event.target.response);
};
transaction.oncomplete = function() {
getPalletDataFromIDB();
}
};
Reading the data:
function getPalletDataFromIDB() {
palletsFromIDB = [];
let transaction = db.transaction(["pallets"], IDBTransaction.READ);
transaction.oncomplete = function(event) {
console.log(event);
};
transaction.onerror = function(event) {
console.log(event.type);
};
let objectStore = transaction.objectStore("pallets");
objectStore.openCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
palletsFromIDB.push(cursor.value);
cursor.continue();
}
transaction.oncomplete = function() {
console.log("[palletsFromIDB] ", palletsFromIDB);
toastr.info("Got pallets");
};
};
};
from web service : {pallets: Array(186)}
from indexedDB : [palletsFromIDB] (151)
One way to do this is to just create a unique keyPath in your json and making that your keyPath in indexed db.
I have created a function to store data in indexed db:
var request = window.indexedDB.open("mynewDB", 1);
request.onupgradeneeded = function(event) {
var db = event.target.result;
var objectStore = db.createObjectStore("toDoList", {keyPath: 'key', autoIncrement: true});
var txn = event.target.transaction;
var addRequest = txn.objectStore("toDoList").add({value: storagedata});
}
(FYI: the storagedata is filled with a base64 string)
If i am executing this function via button the content of variable storagedata is in the IndexedDB. But if i want to press the button again to store another value into the IndexedDB, nothing happens.
In addition to that if i am executing the function the second time the function jumps at line request.onupgradeneeded = function(event) { in to the timeout of file "intervalTrigger-dbg.js" to code clearTimeout(this._delayedCallId);
What i did to solve the problem: debugging in browser and reading a lot of documentations about indexeddb.
I fixed the problem on my own.
For everyone who want to know how it works:
var request = window.indexedDB.open("yourDB-1", 1);
var db;
var transaction;
var store;
request.onupgradeneeded = function(event) {
var db = event.target.result;
var transaction = event.target.transaction;
var store = db.createObjectStore("yourDB", {keyPath: 'key', autoIncrement: true});
}
request.onerror = function (event) {
console.log("Here is a error: " + event.target.errorCode);
}
request.onsuccess = function (event) {
db = request.result;
transaction = db.transaction("yourDB", "readwrite");
store = transaction.objectStore("yourDB");
db.onerror = function(event){
console.log("ERROR" + event.target.errorCode);
}
store.put({value: storagedata});
transaction.complete = function() {
db.close();
}
}
I'm trying to update an Object Store in IndexedDB from a Service Worker, this is my code right now:
function updateUrlLink(url_link) {
var request = indexedDB.open('db', 1);
var url_link_value = url_link;
request.onsuccess = function (event) {
var store = request.result.transaction("url_link", "readwrite").objectStore("url_link");
store.add(url_link_value, "url_link");
};
request.onupgradeneeded = function (event) {
var db = event.target.result;
var store = db.createObjectStore('url_link');
};
}
Is this the right way to update url_link or is there other way?
I'm having trouble saving blob in IndexedDB, and only with blob.
If I save something else (like image as base64), everything works fine.
But with blob, there is simply empty object property saved.
Screenshot from console:
Code:
//prepared blob...
var openRequest = indexedDB.open("testDB",1);
openRequest.onupgradeneeded = function(e) {
var thisDB = e.target.result;
if(!thisDB.objectStoreNames.contains("stash")) {
thisDB.createObjectStore("stash");
}
}
openRequest.onsuccess = function(e) {
db = e.target.result;
var transaction = db.transaction(["stash"],"readwrite");
var store = transaction.objectStore("stash");
var tID = Date.now();
var obj = {
bl:blob,
created:tID
}
console.log(obj);
//add it
var request = store.add(obj, tID);
request.onerror = function(e) {
console.log("Error",e.target.error.name);
}
request.onsuccess = function(e) {
console.log("success");
}
}
openRequest.onerror = function(e) {
//....
}
I also tried to save only blob (not wrapped as obj property), it's the same.
I can save blob to HDD, and if I console log my obj, I get:
So I guess, blob is valid, and problem is in adding it to indexedDB. I'm new to blob/indexedDB, and probably doing some noob mistake.
Can someone please advise, what am I doing wrong?
PS: no error messages at all
Very old question, but there is support now for saving Blobs in IndexedDb:
https://developers.google.com/web/updates/2014/07/Blob-support-for-IndexedDB-landed-on-Chrome-Dev
// Create an example Blob object
var blob = new Blob(['blob object'], {type: 'text/plain'});
try {
var store = db.transaction(['entries'], 'readwrite').objectStore('entries');
// Store the object
var req = store.put(blob, 'blob');
req.onerror = function(e) {
console.log(e);
};
req.onsuccess = function(event) {
console.log('Successfully stored a blob as Blob.');
};
} catch (e) {
var reader = new FileReader();
reader.onload = function(event) {
// After exception, you have to start over from getting transaction.
var store = db.transaction(['entries'], 'readwrite').objectStore('entries');
// Obtain DataURL string
var data = event.target.result;
var req = store.put(data, 'blob');
req.onerror = function(e) {
console.log(e);
};
req.onsuccess = function(event) {
console.log('Successfully stored a blob as String.');
};
};
// Convert Blob into DataURL string
reader.readAsDataURL(blob);
}
As of posting this, the referenced Document was last updated on: Last updated 2019-03-20 UTC.
You can convert Blob or File object to ArrayBuffer object or binarystring and then save it. Convert it back to Blob after you read from indexedDB.
//prepared blob...
blobToBlob2(blob, saveBlob2);
function blobToBlob2(blob, callback){
var reader = new FileReader();
reader.readAsArrayBuffer(blob);
reader.onload = function(e) {
callback({
buffer: e.target.result,
type: blob.type
});
};
}
function blob2ToBlob(blob2){
return new Blob([blob2.buffer],{type:blob2.type});
}
function saveBlob2(blob2){
//..... code
var obj = {
bl:blob2,
created:tID
}
var request = store.add(obj, tID);
//..... code
}
I use Chrome 12 on Mac OS X and I've included jQuery 1.6.1 within the document.
I try to read a File with the following code, an error seams to occur while reading the file, so this.error.onerror() is called, but the FileReader-Object this.reader doesn't exists anymore and I can't get the error. I'm also not sure why the error occurs, it's a regular text document I want to read.
function FileHandler(files, action) {
console.log('FileHandler called.');
this.files = files;
this.reader = new FileReader();
this.action = action;
this.handle = function() {
console.log('FileHandler.handle called.');
for (var i = 0; i < this.files.length; i++) {
this.reader.readAsDataURL(files[i]);
}
}
this.upload = function() {
console.log('FileHandler.upload called.');
console.log(this.reader);
data = {
content: this.reader.result
}
console.log(data);
}
this.error = function() {
console.log('An error occurred while reading a file.');
console.log(this.reader.error);
}
this.reader.onload = this.upload;
this.reader.onerror = this.error;
}
This code creates the following console output:
http://cl.ly/0j1m3j0o3s071Y1K3A25
Inside .onerror, the this is not the same as outside because it's a new function (with a new scope).
Keep track of the this by setting it statically like this:
var _this = this; // _this won't change
this.reader.onerror = function() {
console.log('An error occurred while reading a file.');
console.log(_this.reader.error);
}
This should be the correct way to do it:
reader.onerror = function(event) {
console.error("File could not be read: " + event.target.error);
};