Table.hook('updating')
NOTE: Since Dexie 3.0, there is a new API superior to this hooks API: DBCore. There is NO PLAN for deprecation of this hooks API though, but it in future, we may extract this API to an addon.
Syntax
db.[tableName].hook('updating', function (modifications, primKey, obj, transaction) {
// You may use transaction to do additional database operations.
// You may not do any modifications on any of the given arguments.
// You may set this.onsuccess = function (updatedObj){} when update operation completes.
// You may set this.onerror = callback if update operation fails.
// If you want to make additional modifications,
// return another modifications object
// containing the additional or overridden modifications to make. Any returned
// object will be merged to the given modifications object.
});
Parameters
modifications | An Object where property names are the key-paths to the properties being modified and values are the new values being set. Deletions of properties are represented by a value of undefined, i.e. modifications.hasOwnProperty(propName) will be true, but the value will be undefined. You must not make changes to this object. Instead, you can return a new modifications object containing the additional modifications you want to apply. |
primKey | The primary key of the object being updated |
obj | Object that is about to be updated. This object must not be modified. Instead return a new modification object containing additional or replaced modifications to make. |
transaction | Transaction instance. |
<this context> | Possibility to be notified when the update operation succeeds or fails. Done by setting this.onsuccess = function(){} or this.onerror = function(){} |
Return Value
If you do not want to change any modification, don’t return any value (return undefined). If you want to add additional modifications or change any of the modifications in the given modifications argument, you should return another object containing the additional or overridden modifications to make.
To Unsubscribe
db.[tableName].hook('updating').unsubscribe(yourListenerFunction)
Description
This event is called whenever an existing database object is about to be updated (through any of the following methods: put(), update() or modify(). Calling put() will only result in an updating event in case it results in replacing an existing object, otherwise, if put() results in an object creation, the creating event will be triggered
A subscriber may use the given transaction
object to do additional operations on the database. The chain of operations can be considered atomic since the subscriber can work on the same transaction as being used for updating the object. If any exception or database error event occur, the entire transaction will abort.
If it is desired to make additional modifications, the subscriber may return its own modifications object containing any additional modifications to make.
If it is desired to know whether the modification will succeed or not, use this.onsuccess = function(updatedObj){}
or this.onerror = function(error){}
to be called after the object has been updated. NOTE: Transaction may still be aborted after the onsuccess callback has been called. To execute code after successful update and transaction commit, you may use transaction.on(‘complete’, …).
Error Handling
If subscriber throws an exception, the update operation will fail and the caller of the update operation will get the failure as a Promise rejection that may be caught/handled or not. If the caller of the update operation does not catch the exception using Promise.catch(), the transaction will be aborted.
If a database operation initiated by the subscriber, results in a failure, the transaction will be aborted no matter if the origin caller of the update operation calls catch() or not. However, the origin caller will receive your error if catching transaction failures, but then the transaction has already aborted. If you as the implementer of the subscriber want to ignore errors resulting from your operations, you may catch() your database operations to prohibit transaction from being aborted. However, it is normally better to let the transaction abort in case a failure of your database operation would impinge database consistency.
If setting this.onsuccess or this.onerror, those callback functions are responsible of not throwing any exception. Any code within that callback must either be bullet proof or surrounded by try/catch.
Use Cases of the CRUD events
Dexie CRUD events can be used to implement several addons to Dexie such as:
- Server Synchronization
- Automatic primary key generation
- Full-text search or other custom ways of indexing properties
- Manipulation of returned objects
The add-ons Dexie.Observable.js and Dexie.Syncable.js uses hook('creating')
, hook('updating')
and hook('deleting')
to make the database locally observable as well as syncable with a remote server.
The hook('reading')
is used internally by Dexie.js by the methods Table.defineClass() and Table.mapToClass() in order to make all objects retrieved from database inherit a given class using prototypal inheritance.
Sample: Full-text search
This example is a simple implementation of full-text search index based on multi-valued indexes and Dexie hooks.
var db = new Dexie("FullTextSample");
db.version(1).stores(
{emails: "++id,subject,from,*to,*cc,*bcc,message,*messageWords"}
);
// Add hooks that will index "message" for full-text search:
db.emails.hook("creating", function (primKey, obj, trans) {
if (typeof obj.message == 'string') obj.messageWords = getAllWords(obj.message);
});
db.emails.hook("updating", function (mods, primKey, obj, trans) {
if (mods.hasOwnProperty("message")) {
// "message" property is being updated
if (typeof mods.message == 'string')
// "message" property was updated to another valid value.
// Re-index messageWords:
return { messageWords: getAllWords(mods.message) };
else
// "message" property was deleted (typeof mods.message === 'undefined')
// or changed to an unknown type. Remove indexes:
return { messageWords: [] };
}
});
function getAllWords(text) {
/// <param name="text" type="String"></param>
var allWordsIncludingDups = text.split(' ');
var wordSet = allWordsIncludingDups.reduce(function (prev, current) {
prev[current] = true;
return prev;
}, {});
return Object.keys(set);
}
// Open database to allow application code using it.
db.open();
//
// Application code:
//
db.transaction('rw', db.emails, function () {
// Add an email:
db.emails.add({
subject: "Testing full-text search",
from: "david@abc.com",
to: ["test@abc.com"],
message: "Here is my very long message that I want to write"
});
// Search for emails:
db.emails.where("messageWords")
.startsWithIgnoreCase("v")
.distinct()
.toArray(function (a) {
alert("Found " + a.length + " emails containing a word starting with 'v'");
});
}).catch(function (e) {
alert(e.stack || e);
});
NOTE: Multi-valued indexes are only supported in Opera, Firefox and Chrome. Does not work with IE so far. However, it is also possible to implement it using custom views, which is implemented in FullTextSearch2.js.
Sample Source Locations
- FullTextSearch.js (using multi-valued indexes)
- FullTextSearch2.js (using custom views)
See Also
Table of Contents
- API Reference
- Access Control in Dexie Cloud
- Add demo users
- Add public data
- Authentication in Dexie Cloud
- Best Practices
- Building Addons
- Collection
- Collection.and()
- Collection.clone()
- Collection.count()
- Collection.delete()
- Collection.desc()
- Collection.distinct()
- Collection.each()
- Collection.eachKey()
- Collection.eachPrimaryKey()
- Collection.eachUniqueKey()
- Collection.filter()
- Collection.first()
- Collection.keys()
- Collection.last()
- Collection.limit()
- Collection.modify()
- Collection.offset()
- Collection.or()
- Collection.primaryKeys()
- Collection.raw()
- Collection.reverse()
- Collection.sortBy()
- Collection.toArray()
- Collection.uniqueKeys()
- Collection.until()
- Compound Index
- Consistency in Dexie Cloud
- Consistent add() operator
- Consistent remove() operator
- Consistent replacePrefix() operator
- Consuming Dexie as a module
- Custom Emails in Dexie Cloud
- DBCore
- DBCoreAddRequest
- DBCoreCountRequest
- DBCoreCursor
- DBCoreDeleteRangeRequest
- DBCoreDeleteRequest
- DBCoreGetManyRequest
- DBCoreGetRequest
- DBCoreIndex
- DBCoreKeyRange
- DBCoreMutateRequest
- DBCoreMutateResponse
- DBCoreOpenCursorRequest
- DBCorePutRequest
- DBCoreQuery
- DBCoreQueryRequest
- DBCoreQueryResponse
- DBCoreRangeType
- DBCoreSchema
- DBCoreTable
- DBCoreTableSchema
- DBCoreTransaction
- DBCoreTransactionMode
- DBPermissionSet
- Deprecations
- Derived Work
- Design
- Dexie Cloud API
- Dexie Cloud API Limits
- Dexie Cloud Best Practices
- Dexie Cloud CLI
- Dexie Cloud Docs
- Dexie Cloud REST API
- Dexie Cloud Web Hooks
- Dexie Constructor
- Dexie.AbortError
- Dexie.BulkError
- Dexie.ConstraintError
- Dexie.DataCloneError
- Dexie.DataError
- Dexie.DatabaseClosedError
- Dexie.IncompatiblePromiseError
- Dexie.InternalError
- Dexie.InvalidAccessError
- Dexie.InvalidArgumentError
- Dexie.InvalidStateError
- Dexie.InvalidTableError
- Dexie.MissingAPIError
- Dexie.ModifyError
- Dexie.NoSuchDatabaseErrorError
- Dexie.NotFoundError
- Dexie.Observable
- Dexie.Observable.DatabaseChange
- Dexie.OpenFailedError
- Dexie.PrematureCommitError
- Dexie.QuotaExceededError
- Dexie.ReadOnlyError
- Dexie.SchemaError
- Dexie.SubTransactionError
- Dexie.Syncable
- Dexie.Syncable.IDatabaseChange
- Dexie.Syncable.IPersistentContext
- Dexie.Syncable.ISyncProtocol
- Dexie.Syncable.StatusTexts
- Dexie.Syncable.Statuses
- Dexie.Syncable.registerSyncProtocol()
- Dexie.TimeoutError
- Dexie.TransactionInactiveError
- Dexie.UnknownError
- Dexie.UnsupportedError
- Dexie.UpgradeError()
- Dexie.VersionChangeError
- Dexie.VersionError
- Dexie.[table]
- Dexie.addons
- Dexie.async()
- Dexie.backendDB()
- Dexie.close()
- Dexie.currentTransaction
- Dexie.debug
- Dexie.deepClone()
- Dexie.defineClass()
- Dexie.delByKeyPath()
- Dexie.delete()
- Dexie.derive()
- Dexie.events()
- Dexie.exists()
- Dexie.extend()
- Dexie.fakeAutoComplete()
- Dexie.getByKeyPath()
- Dexie.getDatabaseNames()
- Dexie.hasFailed()
- Dexie.ignoreTransaction()
- Dexie.isOpen()
- Dexie.js
- Dexie.name
- Dexie.on()
- Dexie.on.blocked
- Dexie.on.close
- Dexie.on.error
- Dexie.on.populate
- Dexie.on.populate-(old-version)
- Dexie.on.ready
- Dexie.on.storagemutated
- Dexie.on.versionchange
- Dexie.open()
- Dexie.override()
- Dexie.semVer
- Dexie.setByKeyPath()
- Dexie.shallowClone()
- Dexie.spawn()
- Dexie.table()
- Dexie.tables
- Dexie.transaction()
- Dexie.transaction()-(old-version)
- Dexie.use()
- Dexie.verno
- Dexie.version
- Dexie.version()
- Dexie.vip()
- Dexie.waitFor()
- DexieCloudOptions
- DexieError
- Docs Home
- Download
- EntityTable
- Export and Import Database
- Get started with Dexie in Angular
- Get started with Dexie in React
- Get started with Dexie in Svelte
- Get started with Dexie in Vue
- Hello World
- How To Use the StorageManager API
- Inbound
- IndexSpec
- Indexable Type
- IndexedDB on Safari
- Invite
- Member
- Migrating existing DB to Dexie
- MultiEntry Index
- PersistedSyncState
- Privacy Policy
- Promise
- Promise.PSD
- Promise.catch()
- Promise.finally()
- Promise.on.error
- Promise.onuncatched
- Questions and Answers
- Realm
- Releasing Dexie
- Road Map
- Road Map: Dexie 5.0
- Road Map: Dexie Cloud
- Role
- Run Dexie Cloud on Own Servers
- Sharding and Scalability
- Simplify with yield
- Support Ukraine
- SyncState
- Table
- Table Schema
- Table.add()
- Table.bulkAdd()
- Table.bulkDelete()
- Table.bulkGet()
- Table.bulkPut()
- Table.bulkUpdate()
- Table.clear()
- Table.count()
- Table.defineClass()
- Table.delete()
- Table.each()
- Table.filter()
- Table.get()
- Table.hook('creating')
- Table.hook('deleting')
- Table.hook('reading')
- Table.hook('updating')
- Table.limit()
- Table.mapToClass()
- Table.name
- Table.offset()
- Table.orderBy()
- Table.put()
- Table.reverse()
- Table.schema
- Table.toArray()
- Table.toCollection()
- Table.update()
- Table.where()
- The main limitations of IndexedDB
- Transaction
- Transaction.abort()
- Transaction.on.abort
- Transaction.on.complete
- Transaction.on.error
- Transaction.table()
- Tutorial
- Typescript
- Typescript (old)
- Understanding the basics
- UserLogin
- Version
- Version.stores()
- Version.upgrade()
- WhereClause
- WhereClause.above()
- WhereClause.aboveOrEqual()
- WhereClause.anyOf()
- WhereClause.anyOfIgnoreCase()
- WhereClause.below()
- WhereClause.belowOrEqual()
- WhereClause.between()
- WhereClause.equals()
- WhereClause.equalsIgnoreCase()
- WhereClause.inAnyRange()
- WhereClause.noneOf()
- WhereClause.notEqual()
- WhereClause.startsWith()
- WhereClause.startsWithAnyOf()
- WhereClause.startsWithAnyOfIgnoreCase()
- WhereClause.startsWithIgnoreCase()
- db.cloud.configure()
- db.cloud.currentUser
- db.cloud.currentUserId
- db.cloud.events.syncComplete
- db.cloud.invites
- db.cloud.login()
- db.cloud.logout()
- db.cloud.options
- db.cloud.permissions()
- db.cloud.persistedSyncState
- db.cloud.roles
- db.cloud.schema
- db.cloud.sync()
- db.cloud.syncState
- db.cloud.userInteraction
- db.cloud.usingServiceWorker
- db.cloud.version
- db.cloud.webSocketStatus
- db.members
- db.realms
- db.roles
- db.syncable.connect()
- db.syncable.delete()
- db.syncable.disconnect()
- db.syncable.getOptions()
- db.syncable.getStatus()
- db.syncable.list()
- db.syncable.on('statusChanged')
- db.syncable.setFilter()
- dexie-cloud-addon
- dexie-react-hooks
- liveQuery()
- unhandledrejection-event
- useLiveQuery()
- useObservable()
- usePermissions()