Hold on. We said "you may never write an action, reducer, selector, or effect."
That doesn’t mean you won’t ever. In fact, a critical feature of ngrx-data is that you can add your own properties to collections, additional actions, reducer cases, selectors, etc.
You aren't locked in to the way ngrx-data does things. You can customize almost anything, both at the single entity-type level and for all entity types.
But you ONLY do so when you want to do something unusual … and that, by definition, is not boilerplate.
An entity is an object with long-lived data values that you read from and write to a database.
Operations that access the database are called persistence operations.
An entity refers to some "thing" in the application domain, such as a customer. Such things are unique even as their values change. Accordingly each entity has a unique primary key, also called its identifier.
Each entity object is an instance of an entity type. That type could be represented explicitly as a class or an interface. Or it could just be a bag of data.
To manage entities with ngrx-data, you describe each entity type with entity metadata.
The application's entity model is the set of all entity types in your application that are described with entity metadata.
In some definitions, the entity type and entity model describe both the data and the logic that govern that data such as data integrity rules (e.g., validations) and behaviors (e.g., calculations). The current version of ngrx-data library is unaware of entity logic beyond what is strictly necessary to persist entity data values.
No! The ngrx-data library is narrowly focused on a single objective: to simplify management of entity data.
Entity data are a particularly opportune target for simplification because they appear in high volume in many applications and the sheer number of similar-but-different ngrx code artifacts necessary to manage that data is daunting.
Anything we can do to shrink entity management code and to leverage the commonalities across entity types will repay the effort handsomely.
But entity data is only one kind of application data.
Configuration data, user roles, the user's prior selections, the current state of screen layouts ... these are all important and highly idiosyncratic data that can benefit from custom coding with standard ngrx techniques.
Data streamed from remote sources such as trading systems, mobile asset tracking systems, and IoT devices are not entity data and may not be a good fit for the ngrx-data library. They are still worth managing with ngrx.
It bears repeating: the ngrx-data library is good for querying, caching, and saving entity data ... and that's it.
Ngrx is a collection of libraries for writing Angular applications in a "reactive style" that combines the redux pattern and tools with RxJS Observables.
Ngrx-data
builds upon three ngrx libraries:
@ngrx/store,
@ngrx/effects, and
@ngrx/entity.
The ngrx-data library extends @ngrx/entity.
The @ngrx/entity library provides the
core representation of a single entity collection within an ngrx store.
Its EntityAdapter
defines common operations for querying and updating individual cached entity collections.
The ngrx-data library leverages these capabilities while offering higher-level features including:
-
metadata-driven entity model.
-
actions, reducers, and selectors for all entity types in the model.
-
asynchronous fetch and save HTTP operations as @ngrx/effects.
-
a reactive
EntityCollectionService
with a simple API that encapsulates ngrx interaction details.
Nothing is hidden from you. The store, the actions, the adapter, and the entity collections remain visible and directly accessible.
The fixes and enhancements in future @ngrx/entity versions flow through ngrx-data to your application.
Redux is an implementation of a pattern for managing application state in a web client application.
It is notable for:
-
Holding all shared state as objects in a single, central store.
-
All objects in the store are immutable. You never directly set any property of any object held in a redux store.
-
You update the store by dispatching actions to the store.
-
An action is like a message. It always has a type. It often has a payload which is the data for that message.
-
Action instances are immutable
-
Action instances are serializable (because the redux dev tools demand it and we should be able to persist them to local browser storage between user sessions);
-
All store values are immutable and serializable.
-
actions sent to the store are processed by reducers. A reducer may update the store by replacing old objects in the store with new objects that have the updated state.
-
All reducers are “pure” functions. They have no side-effects.
-
The store publishes an event when updated by a reducer.
-
You application listens for store events; when it hears an event of interest, the app pulls the corresponding object(s) from the store.
Ngrx is similar in almost all important respects. It differs most significantly in replacing events with observables.
Ngrx relies on RxJS Observables to listen for store events, select those that matter, and push the selected object(s) to your application.
State is data. Applications have several kinds of state including:
-
application state is session data that determine how your application works. Filter values and router configurations are examples of application state.
-
persistent state is "permanent" data that you store in a remote database. Entities are a prime example of persistent state.
-
shared state is data that are shared among application components and services.
In ngrx, as in the redux pattern, all stored state is (or should be) immutable. You never change the properties of objects in the store. You replace them with new objects, created through a merge of the previous property values and new property values.
Arrays are completely replaced with you add, remove, or replace any of their items.
RxJS Observables is a library for programming in a "reactive style".
Many Angular APIs produce RxJS Observables so programming "reactively" with Observables is familiar to many Angular developers. Search the web for many helpful resources on RxJS.
Some folks try to conquer the "too much boilerplate" problem by generating the code.
Adding the Foo
entity type? Run a code generator to produce actions, action-creators, reducers, effects, dispatchers, and selectors for Foo
.
Run another one to product the service that makes HTTP GET, PUT, POST, and DELETE calls for Foo
.
Maybe it generates canned tests for them too.
Now you have ten (or more) new files for Foo
. Multiply that by a 100 entity model and you have 1000 files. Cool!
Except you're responsible for everyone of those files. Overtime you're bound to modify some of them to satisfy some peculiarity of the type.
Then there is a bug fix or a new feature or a new way to generate some of these files. It's your job to upgrade them. Which ones did you change? Why?
Good luck!