I am looking to re-design and expand on a single-page application I am developing. I like the design methodology behind Webix-Jet and started to rework completed aspects of my app using Jet. So far so good except for finding any sort of documentation on how to create views and models for dealing with data stored in IndexedDb or using the Dexie.js wrapper. I was planning on creating a single model for interacting with all stores with further specificity in the view files or additional models as necessary. However, I have not been able to get anything to work. With the current build of Webix-Jet, is it possible? If so, how would you setup a model to return all of the records from a store? Is it possible to sync the records like you can with server-side databases or do you create this functionality outside of Webix using vanilla javascript?
Hello James_S_Hackney,
We have several ways to store and interact with data. Here you can find more information about all these ways.
Unfortunately we do not have a ready-made solution and to integrate indexedDB or Dexie.js we indeed need to use vanilla javascript.
We used to have a proxy made for IndexedDB, it was deprecated in Webix 7.0 as a rarely used API, but the good news is that it’s still available in our legacy repo and you can reuse it as a custom proxy.
Here is the instructions of how to work with it: how to work
There’s no specific solution for Dexie, but you can alter the proxy or try something else, e.g. a Jet model or a Jet service.
Please look at some examples below.
- Using DataCollection and models:
Initialize the database:
// db.js
import Dexie from "dexie";
import dexieCloud from "dexie-cloud-addon";
const db = new Dexie('SyncedRecords', {addons: [dexieCloud]});
db.version(1).stores({
records: 'id, title, year, votes, rating, rank'
});
// Connect your dexie-cloud database:
db.cloud.configure({
databaseUrl: "https://YOURURL.dexie.cloud",
requireAuth: true // optional
});
export default db;
Create the DataCollection and subscibe to its CRUD operations.
/ records.js
import db from "./db";
const data = new webix.DataCollection();
// subscribe to collection CRUD operations and update data in the db
data.data.attachEvent("onStoreUpdated", (id, obj, mode) => {
if (mode) {
switch (mode) {
case "add":
obj.id += ""; // current settings require a string
db.records.add(obj);
break;
default:
alert("todo");
}
}
});
// get all data
data.parse(db.records.toArray());
// export the colletion
export default data;
Loading data to the view components and doing some operations on them ( add, update, delete ):
// data.js
export default class DataView extends JetView {
config() {
return {
rows: [
{ view: "button", value: "Add", click: () => data.add({ title: "New film" }) },
{ localId: "table", view: "datatable", autoConfig: true }
]
}
}
init() {
this.$("table").parse(data);
}
}
- Implementation with a service.
The service also has a DataCollection inside, but the difference is that the architecture is cleaner, you access the collection via methods of the service. Also, this approach can implement a different order of saving - first to the database, next locally.
// records.js
import db from "./db";
export default class LocalData {
constructor() {
this.data = new webix.DataCollection();
}
getRecords(reload) {
if (!this.ready || reaload) {
this.data.clearAll();
this.data.parse(db.records.toArray());
this.ready = true;
}
return this.data;
}
addRecord(obj) {
obj.id += ""; // current settings require a string
return db.records.add(obj).then(id => {
obj.id = id; // if the db assigns its own ID
return this.data.add(obj);
});
}
// todo other operations
}
Then we can initialize this service in the app.js file and it will be accessible in all views::
// app.js
constructor(config) {
...
this.setService("local", new LocalData());
}
And you can use this service by calling its methods like this::
// data.js
config() {
return {
rows:[
{ view:"button", value: "Add", click: () => this.data.addRecord({ title: "New film" }) },
{ localId: "table", view:"datatable", autoConfig:true }
]
};
}
init() {
this.data = this.app.getService("local");
this.$("table").parse(data.getRecords());
}
Since we do not have enough expertise in IndexedDB itself, we can only provide a basic example and help with describing how Webix and Jet can interact with data from the outside. You can either use the proxy or create a model or a service in a similar way. We can also help with problems that concern Webix or Jet in your existing solution, so you are welcome to share the solution you tried to implement as well.
I can not tell you how much I appreciate your response. I have not tried your recommendations yet as I have been busy implementing a solution I came up with that worked perfectly on one view but blew up when I applied it against my other views. I am using the menu plugin and the first view I select works but the next view I select throws an error because the system can not destruct the binding from the first view. I think I will go back and start from scratch and use your examples to create a simple application that proves it will work. This will also give me something simple to post back if I have any issues.