Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Customers and Orders
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Getting started with NgRx Auto-Entity is easy!
If you are already familiar with NgRx, then adding Auto-Entity to your Angular application is very easy. There are four major steps required to add the module, create new entity state, and provide your entity services.
First things first, you must bring in the NgrxAutoEntityModule
into your app module and call the forRoot()
method to configure the library.
Before you can actually create your state, you will need to create your entity models, as you would normally do. Auto-Entity requires two small changes to how you create models for NgRx.
You will also need to create an entity service to handle CRUD behavior for each entity. Entity services may be shared if your API uses a common pattern. Otherwise you may need to implement a service for each entity as you usually do with NgRx.
In the example above we have a simple shared entity service that supports a basic REST API where each entity conforms to a simple pattern:
/<rootUrl>/<entityName>[/<key>]
Auto-Entity provides basic entity metadata, such as the model name, in the entityInfo
parameter of each entity service method.
Once you have created an entity service or services, you will need to provide them in your app module. With Auto-Entity, services must be provided in a slightly different manner than normal, to ensure that Auto-Entity is able to find entity services dynamically.
In our example here, we are sharing a single entity service, EntityService
, for all entities. We must provide
each model and useClass
to specify the service class to use.
Finally, now that you have your models and have provided your entity services, you need to build your state for each model. Add a new state file for each model following the pattern depicted here:
Finally, include your entity states in the AppState interface, and your stub reducers in the action reducer map:
With that, you are ready to start using your automatic entity state! Continue on to the next section to learn how.
Create application state interface.
As with any NgRX application, we need to create a new app.state.ts file. We recommend creating this file in a root state directory, located at src/app/state. Import the IEntityState
interface from @briebug/ngrx-auto-entity as well, as we will be using it later.
Define the IAppState
interface as normal. We will eventually define each entity state property here. For now, we've left it blank, and will fill it in later on in this quick start.
Remember to export the AppState
type so that it may be used throughout the rest of your app.
Adding NgRx & Auto-Entity to an App
If you have not used NgRx before, and need to start from scratch, this guide should get you going. Let's start by creating a state module. We recommend creating this module in a root state directory, located at src/app/state. In this directory, create a new state.module.ts file:
Import the NgRx StoreModule
and EffectsModule
as well as the Auto-Entity NgrxAutoEntityModule
. Make sure you call the .forRoot()
initializer on each of them to ensure they are properly imported. It is important that the NgrxAutoEntityModule be brought in after the EffectsModule, as this ensures all automatic effects will be properly registered.
The NgRx Auto Entity module is now imported in your application, giving you access to ready-made generic actions, automatic effects, pre-defined reducers and prefabricated facade classes to handle the bulk of your CRUD meeds.
, we need to set up the state of our application.
Create your entity models.
In a departure from classic @ngrx/entity models, each model in your application should be defined as a class (see note below). Here is an example of a Customer
model:
Next we need to import the Key
decorator. This is used to specify the property in your model that is the unique identifier. Decorate the id
property, which is the unique identifier for Customer
model. Read more about entity keys in the advanced documentation.
Note that the model must be a class and not an interface. This is because interfaces are a compile-time only feature of TypeScript, while classes are a native runtime construct in JavaScript.
Create application reducer and meta reducer.
Also like normal NgRX apps, add a reducer map to your app.state.ts file. We recommend creating this file in a root state directory, located at src/app/state.
In versions of NgRx Auto-Entity prior to v0.2, the developer was also responsible for including the autoEntityMetaReducer
in the app meta reducers collection. As of version 0.2 of the library, import of the NgrxAutoEntityModule
with the .forRoot()
call is all that is necessary to include the meta reducer.
If you are upgrading from a version prior to v0.2, you should remove the autoEntityMetaReducer
from your app meta reducers!
With NgRx 8, runtime checks have replaced the need to use the storeFreeze meta reducer. As such, a standard state configuration no longer requires any meta reducers.
Create application state module.
Now that we have implemented our root state interface & reducer map, we need to update the state module we created in the first step:
Update the import of the StoreModule
. In the forRoot()
static method, specify the appReducer
and appMetaReducers
from your previously created app.reducer
as with any normal NgRX app.
If you have any custom effects you may have implemented, include those classes in the EffectsModule
import's forRoot()
call. Effects are optional with NgRx Auto-Entity, so if you have no effects just pass an empty array.
Define the initial entity state
In our example we are building the state for the Customer
entity. As such, we've created a new customer.state.ts file located at src/app/state/customer.state.ts.
Import the buildState
function from the ngrx-auto-entity module. This function builds the initial state and selectors for each entity. Call the function by passing in the Customer entity class (note, the class must be passed in!) We use object destructuring on the return type access the initialState
, selectors
and facade
base class from the result of buildState
.
We can now further destructure the selectors object to map each type of standard selector to model-specific names for import into other modules:
selectAll
selects the Array
of entities
selectEntities
selects the Dictionary
of entities
selectIds
selects the Array
of entity identifiers (keys)
selectTotal
selects the number
of entities
Note that retrieving and exporting the selectors are optional if you extract the facade. The facade base class generated by buildState fully encapsulates all of the functionality you will need to interact with your entity state, and we generally recommend only using the facade. Demonstration of how to access selectors directly, such as in the event that you may need to create your own custom selectors, is simply for completeness here.
There are additional selectors bundled as part of each custom entity state built by buildState
that may be mapped to state-specific names. Read more in the advanced documentation.
When the selectors object is destructured we alias the selectors with entity-friendly names to avoid naming conflicts.
Finally, we define the customerReducer
function. The reducer function accepts two arguments: state
, which defaults to the initialState
, and the action
.
A reducer function is necessary to configure the NgRX standard actionsReducer
we defined earlier. For most entities, you will not need to do anything other than return the state passed in, as the autoEntityMetaReducer
will handle reduction for you. If custom reduction is required for your apps, it may be handled in these reducers.
Encapsulate!
In our CustomerComponent
, there are a few methods that exhibit "class envy" which is a kind of anti-pattern. For those not familiar with the concept, class envy occurs when methods of one class are more dependent on functionality within another class. It then becomes prudent to move the method into the class of envy, and if necessary parameterize any input required from the method's previous home.
Our CustomerComponent
has two potential candidates for encapsulation within our CustomerFacade
class: hasCustomer
and onSave. We can easily move this functionality into our facade class and make these behaviors reusable in any component that may require interaction with customer entity state:
First, your models must be classes rather than interfaces (see for more info.) Second, your entity identity must be decorated with the @Key
directive. For entities with composite keys, simply decorate each property that is part of the key.
Entity facades include a considerable amount of ready-to-go functionality. Check out the advanced facade documentation to learn more about everything our facades provide and how to extend them.
Module
Minimum Required Version
@angular/common
8.0.0
@angular/core
8.0.0
@ngrx/effects
8.0.0
@ngrx/store
8.0.0
rxjs
6.0.0
Leverage the power of facades
Now that you have set up state for an entity, it is time to start using it. With NgRx Auto-Entity, if you leverage our pre-fabricated facades, we have made using state about as easy as it can get. Start by creating a facade class that derives from the facade base class generated by your call to buildState
:
With your facade in hand, inject it into your component and use the facade to interact with your entities:
Note the changes here. We imported only the activated route and a facade into our component. Our component does not import any state-related types at all. No actions, no store, no app state interface, none of the usual suspects. All state interactions occur through the facade.
That junk don't belong here!
Once you have enhanced your facade with functionality that belongs in the facade and not the component, it's time to clean up your component. Using the new functionality we have implemented in our customer facade, our component can become reduced to a simpler form:
Update the application state interface.
Now that we have the standard initial implementation for NgRX and Auto-Entity in place, we need to wire our models into our state.
Note that we have added a new customer
property to the IAppState
interface of type IEntityState<Customer>
, which we imported from @briebug/ngrx-auto-entity
at the top of the file.
For most basic CRUD states, you will not need to implement any custom state interfaces, effects or reducers. This is the simplicity that NgRX Auto-Entity brings to the table!
After we create the entity reducer, we'll also need to update the appReducer
constant to include the customer
property (with the customer reducer function as the value). It's important that both properties have the same name.
Learn how to make NgRX Auto-Entity for you
NgRX Auto-Entity aims to provide a seamless means of utilizing a standard set entity actions and effects with minimal repetitive code requirements, while preserving the fundamental nature of NgRX itself. This library is not a replacement for or alternative to NgRX. It works within the standard paradigm that NgRX has set forth, making use of actions, reducers & effects like any other NgRX application.
What Auto-Entity does do is provide a set of ready-made, generic actions for handling all of the standard CRUD operations for entities, so you neither have to write nor generate any of that code yourself. Auto-Entity presents a flexible framework that you may use in its entirety for all of your entity needs, or use piecemeal as necessary in order to achieve your specific goals.