Angular 14+ wrapper for RxDB - A realtime Database for the Web
demo - based on TodoMVC
If you don't want to setup RxDB manually in your next Angular project - just import NgxRxdbModule
or go with provideRxDatabase
and provideRxCollection
if standalone component is your choice.
RxDB | Angular 14+ |
---|---|
npm install @ngx-odm/rxdb
AppModule
import { NgxRxdbModule } from '@ngx-odm/rxdb';
import { getRxDatabaseCreator } from '@ngx-odm/rxdb/config';
@NgModule({
imports: [
// ... other imports
NgxRxdbModule.forRoot(
getRxDatabaseCreator({
name: 'demo', // <- name (required, 'ngx')
storage: getRxStorageDexie(), // <- storage (not required, 'dexie')
localDocuments: true,
multiInstance: true, // <- multiInstance (optional, default: true)
ignoreDuplicate: false,
options: {
plugins: [
// will be loaded by together with core plugins
RxDBDevModePlugin, // <- add only for development
RxDBAttachmentsPlugin,
RxDBLeaderElectionPlugin,
],
storageType: 'dexie|memory', // <- storageType (optional, use if you want defaults provided automatically)
dumpPath: 'assets/dump.json', // path to datbase dump file (optional)
},
})
),
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
FeatureModule
Example :Schemas define how your data looks. Which field should be used as primary, which fields should be used as indexes and what should be encrypted. The schema also validates that every inserted document of your collections conforms to the schema. Every collection has its own schema. With RxDB, schemas are defined with the jsonschema-standard which you might know from other projects. https://rxdb.info/rx-schema.html
import type { RxCollectionCreatorExtended } from '@ngx-odm/rxdb/config';
// create or import your schema
const todoSchema: RxSchema = require('../../../assets/data/todo.schema.json');
// create config
const todoCollectionConfig: RxCollectionCreatorExtended = {
name: 'todo', // <- name (required)
schema: todoSchema, // <- schema (not required, see below)
localDocuments: true,
options: {
initialDocs: [], // docs to be imported into empty collection (optional)
schemaUrl: 'assets/data/todo.schema.json', // load schema from remote url (optional)
replicationStateFactory: collection => {
// provide replication state (optional)
},
},
};
@NgModule({
imports: [
// ... other imports
NgxRxdbModule.forFeature(todoCollectionConfig),
],
})
export class TodosModule {
constructor(
@Inject(RXDB_COLLECTION) private collectionService: RxDBCollectionService<Todo>
) {
this.collectionService.sync(); // INFO: collection is ready
}
}
FeatureService
import { RXDB_COLLECTION } from '@ngx-odm/rxdb';
import { RxDBCollectionService } from '@ngx-odm/rxdb/collection';
@Injectable()
export class TodosService {
private collectionService: RxDBCollectionService<Todo> =
inject<RxDBCollectionService<Todo>>(RXDB_COLLECTION);
// store & get filter as property of a `local` document
filter$ = this.collectionService
.getLocal('local', 'filterValue')
.pipe(startWith('ALL'), distinctUntilChanged());
// get count of documents in collection as observable
count$ = this.collectionService.count();
// get documents from collection as observable
// optionally using `RxQuery` mango-queries
todos$: Observable<Todo[]> = this.collectionService.docs();
// add new document
add(name: string): void {
const payload: Todo = { guid: uuid(), name, done: false, dateCreated: Date.now() };
this.collectionService.insert(payload);
}
// update property of single document
toggle(guid: string, done: boolean): void {
this.collectionService.set(guid, { done });
}
// update many documents with partial data by query
toggleAllTodos(completed: boolean) {
this.collectionService.updateBulk(
{ selector: { completed: { $eq: !completed } } },
{ completed }
);
}
// remove many dcouments by qeury
removeCompletedTodos(): void {
this.collectionService.removeBulk({ selector: { completed: true } });
}
// ...
}
main.ts
import { provideRxDatabase } from '@ngx-odm/rxdb';
import { getRxDatabaseCreator } from '@ngx-odm/rxdb/config';
export const appConfig: ApplicationConfig = {
providers: [
// ... other providers
provideRxDatabase(
getRxDatabaseCreator({
name: 'demo',
localDocuments: true,
multiInstance: true,
ignoreDuplicate: false,
storage: getRxStorageDexie(),
plugins: [
// will be loaded by together with core plugins
RxDBDevModePlugin, // <- add only for development
RxDBAttachmentsPlugin,
RxDBLeaderElectionPlugin,
],
})
),
],
};
bootstrapApplication(AppComponent, appConfig).catch(err => console.error(err));
Component
import { provideRxCollection } from '@ngx-odm/rxdb';
@Component({
standalone: true,
// ...
providers: [provideRxCollection(config)],
})
export class StandaloneComponent {
readonly todoCollection = inject(NgxRxdbCollectionService<Todo>);
}
sginals
& signalStore
from @ngrx/signals
import { signalStore } from '@ngrx/signals';
import { withEntities } from '@ngrx/signals/entities';
import { withCollectionService } from '@ngx-odm/rxdb/signals';
import { withDevtools } from '@angular-architects/ngrx-toolkit';
export const TodoStore = signalStore(
{ providedIn: 'root' },
withDevtools('todo'),
withEntities<Todo>(),
// INFO: an instance of RxCollection will be provided by this
withCollectionService<Todo, TodosFilter, RxCollectionCreatorExtended>({
filter: 'ALL' as TodosFilter,
collectionConfig: TodosCollectionConfig,
}),
...
);
@Component({
standalone: true,
// ...
providers: [TodoStore],
})
export class StandaloneComponent {
readonly todoStore = inject(TodoStore);
constructor() {
effect(() => {
const { filter, entities } = this.todoStore;
});
}
}
By using this module you can simplify your work with RxDB in Angular application:
@ngrx/signals
and @ngrx/entity
(optionally zoneless) (see example)query-params-plugin
(in demo, set localStorage _ngx_rxdb_queryparams
)Project is: in progress
Project inspired by
withDataService
from Angular ArchitectsCreated by @voznik - feel free to contact me!