js-data

Respect Your Data

Give your data the treatment it deserves with a framework-agnostic, datastore-agnostic JavaScript ORM built for ease of use and peace of mind. Works in Node.js and in the Browser.

Get Started

Events & Listeners

Most JSData classes inherit from the Component class, granting them some eventing capabilities. There a number of built-in events that will be fired under normal operation, but you can add custom events as well.

Tip

Leveraging events, you can use JSData to implement a Flux architecture.

Listening for events

You can place event handler functions on instances of JSData classes via on and off methods.

import { DataStore } from 'js-data';

const store = new DataStore();

store.defineMapper('buildings');

const storeChangeHandler = (mapperName, data) => {
	console.log(`${mapperName} has changed`, data)
};

store.on('add', storeChangeHandler);

store.add('buildings', { name: 'Warehouse' }); // triggers store 'add' event

// turn off the listener/remove event handler
store.off('add', storeChangeHandler);

Event bubbling

Some JSData components are containers for other JSData components. When the child components emit events, those events will bubble up and be emitted on the parent component as well. Record events bubble up to their containing Collection, Mapper events bubble up to their containing store, etc.

Example

import { DataStore } from 'js-data';

const store = new DataStore();

store.defineMapper('document', {
  endpoint: 'documents',
  schema: {
    track: true,
    properties: {
      id: { type: 'number' },
      title: { type: 'string' },
      content: { type: 'string' }
    }
  }
});

const doc = store.add('document', {
  title: 'Lessons Learned',
  content: '...'
});

store.on('change', (mapperName, record, changes) => {
	console.log(`Event bubbled up from ${mapperName} record.`);
  console.log(record, changes);
});

doc.on('change', (record, changes) => {
	console.log(`Event emitted on record.`);
  console.log(record, changes);
});

doc.title = 'Lessons I need to Learn'; // will trigger a change event

Built-in Events

All Events

Async Lifecycle Events

CRUD operations trigger lifecycle events on DataStore, SimpleStore, Container, and Mapper instances.

  • all (fires on all events)
  • afterCreate
  • afterCreateMany
  • afterDestroy
  • afterDestroyAll
  • afterFind
  • afterFindAll
  • afterUpdate
  • afterUpdateAll
  • afterUpdateMany
  • beforeCreate
  • beforeCreateMany
  • beforeDestroy
  • beforeDestroyAll
  • beforeFind
  • beforeFindAll
  • beforeUpdate
  • beforeUpdateAll
  • beforeUpdateMany

Sync Events

DataStore, SimpleStore, LinkedCollection, and Collection instances will emit these events when records are added, removed, or changed.

Instances of Record can emit a change event. See Tracking changes.

Custom Events

You can declare custom event names as a string using on, off, & emit.

import { DataStore } from 'js-data';

const store = new DataStore();

store.defineMapper('animals');

// set a listener/handler on the DataStore instance
store.on('animalNoise', (mapperName, data) => {
  console.log(`DataStore event 'animalNoise' fired on mapper ${mapperName}`, data);
});

store.emit('animalNoise', 'animals', { type: 'growl', species: 'tiger' });
import { DataStore } from 'js-data';

const store = new DataStore();

const carsMapper = store.defineMapper('cars')

// set a listener only on our cars Mapper instance
carsMapper.on('honk', (record) => {
  console.log(`carsMapper event 'honk' fired`, record);
});

carsMapper.emit('honk', { type: 'mercedes', color: 'yellow' });