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.
First, your models must be classes rather than interfaces (see advanced documentation 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.
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.
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.
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:
Entity facades include a considerable amount of ready-to-go functionality. Check out the advanced facade documentation here to learn more about everything our facades provide and how to extend them.
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.
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:
Create service for handling data interactions with server
In our example we are creating a service for persisting entities via a simple REST API. As such, we've created a new entity.service.ts file and defined an injectable EntityService
class.
It's important that each entity service implement the IAutoEntity
interface. This interface supports the following methods:
load()
loadAll()
loadMany()
loadPage()
loadRange()
create()
createMany()
update()
updateMany()
replace()
replaceMany()
delete()
deleteMany()
These methods perform the CRUD operators for entity retrieval and persistence.
To create an entity service, we must import the IAutoEntityService
and IEntityInfo
interfaces. The entity service must implement the IAutoEntityService
interface. The IEntityInfo
object provides metadata about the entities, which can be used to help build urls if necessary.
Finally, we implement each of the necessary methods for retrieving and persisting an entities.
Your implementation may vary based on the method of persistence and the architecture of your API. Each method is optional, and may be implemented on an as-needed basis for each entity. We provide several options for loading data, as well as options for updating (PATCH) or replacing (PUT) entities. Implement what you need.
Learn about the required paradigm changes for Auto-Entity
For NgRX Auto-Entity to function properly, some minor changes will be required in the way you implement a couple standard bits of code. This includes service implementations and model implementations. These changes are not particularly significant, and for services we provide a lot of meta information to assist you in achieving whatever is necessary for your applications.
As models and services are standard elements of any Angular application, there should be no additional boilerplate code to implement here. These would be implemented regardless. However, be aware of the nuanced changes in how the model and service are used, and the explicit interface requirement for the service.
More significant changes occur when utilizing facades to interact with state. Facades encapsulate the complexities of @ngrx, presenting you with a simplified, logical and more standard API into working with your stateful data.
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.
Simplifying Reactive State!
NgRx Auto-Entity is a library that simplifies reactive state in @ngrx
with reusable generic actions, automated effects & reducers and prefabricated facades.
NgRX Auto-Entity is an add-on library for @ngrx
that aims to greatly simplify use of @ngrx
and reduce the implementation load of adding @ngrx
to your application. We provide a set of ready-made, generic actions that cover most of the common use cases such as loading entities and sets of entities as well as creating, updating or replacing, and deleting entities.
Auto-Entity wires in ready-made effects to handle standard behaviors, as well as provides a core meta reducer that reduces all entity state managed by this library. For most use cases, the implementation burden for you the developer will be limited to basic initial @ngrx
setup, creation of models for each entity & creation of services for each entity. This is functionality that would need to be implemented by you the developer regardless.
Where we save you time is by eliminating the need to implement unique sets of CRUD actions for each and every entity, as well as the side effects that handle standard CRUD behavior for each and every entity. This can be a significant amount of development effort for each @ngrx
application, and we hope the savings we offer will allow you to focus on solving the critical business needs of your customers.
Further, Auto-Entity generates pre-fabricated Facades around your entity state, allowing you to extract all @ngrx
and other state related code from your components, encapsulate them in a facade layer that presents a much simpler, more logical and easier to comprehend and use API for your entities.
Understand changes to service implementation
With a normal @ngrx application, you are free to implement services however you see fit. There are no explicit requirements by @ngrx, since you are also on the hook to implement the effects as well, and it is your own effects that call your services.
NgRX Auto-Entities dynamic nature requires that data services implement the IAutoEntityService<TModel>
interface. This interface defines the contract by which Auto-Entity interacts with your services. This interface is described as follows:
This interface defines a different method that corresponds to each different kind of initiating generic action provided as a part of the NgRX Auto-Entity library. Every method provides entityInfo
as the first parameter, which contains metadata about the entity, including its name (based on the class name you defined for the model) as well as its type (the class you defined for the model). Each method also accepts a variety of other parameters, whatever may be necessary to support the unique behavior of that method.
Note that each method of the IAutoEntityService
interface is optional. Implement only what you need!
In addition to the basic CUD operations, we also support bulk versions of each CUD operation, as well as several options for loading entities. Each of the different load operations support different behavioral semantics, defined by the initiating actions and guiding how the meta reducer handles the data in state.
Each method of the IAutoEntityService
interface accepts, as the last parameter, custom criteria
. This allows you, the developer, to include any additional, arbitrary details that may be necessary to facilitate the desired operation, for any operation supported by this library.
Finally, in order for NgRx Auto-Entity to find the entity service you just created, you must provide it in your application state. Providing entity services is slightly different than a normal provider, which simply provides itself as the service class.
Here, we have provided the model type as the provider, and specified the EntityService
class as the actual service class via useClass
. This is the simplest model for using Auto-Entity, and for simple backend APIs that follow a common pattern, a single service like this may be reused for any number of entities.
provide: Entity, useClass: EntityService
In the event that you have a more complex backend API, or even must integrate with many backend APIs, you may create custom entity services for each entity if necessary, and provide each model with its own unique service class following the same pattern as above.
Finally, import the StateModule
we created earlier into your root AppModule
to bring in all of your root state, including NgRx Auto-Entity.
And, with that, you are done! You can now start using your entity in your app.
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.