Angular NgRx Entity

Learn Angular NgRx Entity with EntityState, EntityAdapter, normalized state, CRUD operations, selectors, Signals integration, enterprise architecture, best practices, and interview questions.

Managing collections such as:

  • Customers
  • Orders
  • Products
  • Employees
  • Accounts
  • Transactions

is one of the most common requirements in enterprise Angular applications.

Without a standardized approach, reducers become repetitive with duplicate CRUD logic.

NgRx Entity solves this problem by providing utilities to manage collections in a normalized, efficient, and scalable way.

It dramatically reduces boilerplate code while improving performance and maintainability.


Table of Contents

  1. What is NgRx Entity?
  2. Why Use NgRx Entity?
  3. Entity Architecture
  4. Normalized State
  5. EntityState
  6. EntityAdapter
  7. CRUD Operations
  8. Entity Selectors
  9. Signals Integration
  10. Enterprise Banking Example
  11. Best Practices
  12. Common Mistakes
  13. Top 10 Interview Questions
  14. Interview Cheat Sheet
  15. Summary

What is NgRx Entity?

NgRx Entity is an extension of NgRx Store that simplifies managing collections of objects.

Instead of writing repetitive reducer logic for:

  • Add
  • Update
  • Delete
  • Replace
  • Upsert

EntityAdapter provides optimized helper methods.


Why Use NgRx Entity?

Without Entity

  • Duplicate reducer logic
  • Manual array manipulation
  • Slower lookups
  • Difficult maintenance

With Entity

  • Less boilerplate
  • Faster CRUD operations
  • Normalized data
  • Efficient selectors
  • Better scalability

Entity Architecture

flowchart LR

Component

Component --> Action

Action --> Reducer

Reducer --> EntityAdapter

EntityAdapter --> Store

Store --> Selectors

Selectors --> Component

Traditional State

Many beginners store data like this:

export interface CustomerState {

customers: Customer[];

loading: boolean;

}

Finding one customer requires searching the array.

customers.find(

customer =>

customer.id === id

);

Time complexity:

O(n)

Normalized State

NgRx Entity stores collections differently.

export interface CustomerState

extends EntityState<Customer> {

loading: boolean;

}

Internally

CustomerState

ids:
[1,2,3]

entities:

1 -> Customer

2 -> Customer

3 -> Customer

Lookups become much faster.


Entity State Architecture

flowchart TD

API

API --> EntityAdapter

EntityAdapter --> ids

EntityAdapter --> entities

ids --> Store

entities --> Store

Creating an Entity Adapter

import {

createEntityAdapter,

EntityAdapter,

EntityState

} from '@ngrx/entity';

export interface CustomerState

extends EntityState<Customer>{

loading:boolean;

}

Create adapter

export const adapter =

createEntityAdapter<Customer>();

Initial State

export const initialState =

adapter.getInitialState({

loading:false

});

Instead of manually creating arrays,

Entity creates the normalized structure.


CRUD Operations

Add One

adapter.addOne(

customer,

state

);

Add Many

adapter.addMany(

customers,

state

);

Update One

adapter.updateOne(

{

id:customer.id,

changes:customer

},

state

);

Remove One

adapter.removeOne(

customerId,

state

);

Remove Many

adapter.removeMany(

ids,

state

);

Set All

adapter.setAll(

customers,

state

);

Upsert One

adapter.upsertOne(

customer,

state

);

Updates existing records or inserts new ones.


CRUD Flow

flowchart LR

Action

Action --> Reducer

Reducer --> EntityAdapter

EntityAdapter --> Store

Reducer Example

export const customerReducer =

createReducer(

initialState,

on(

loadCustomersSuccess,

(state,{customers}) =>

adapter.setAll(

customers,

state

)

),

on(

addCustomerSuccess,

(state,{customer}) =>

adapter.addOne(

customer,

state

)

)

);

Notice how little code is required.


Entity Selectors

Entity generates selectors automatically.

const {

selectAll,

selectEntities,

selectIds,

selectTotal

}

=

adapter.getSelectors();

Available Selectors

Selector Description
selectAll Returns all entities as an array
selectEntities Returns entity dictionary
selectIds Returns all IDs
selectTotal Returns entity count

Entity Selector Architecture

flowchart LR

Store

Store --> EntitySelectors

EntitySelectors --> Component

Sorting Entities

EntityAdapter supports sorting.

export const adapter =

createEntityAdapter<Customer>({

sortComparer:

(a,b)=>

a.name.localeCompare(

b.name

)

});

Now all entities remain sorted automatically.


Custom Entity ID

Default ID

id

Custom ID

createEntityAdapter<Customer>({

selectId:

customer =>

customer.customerNumber

});

Useful when APIs use different identifiers.


Signals Integration

Selectors work perfectly with Signals.

customers =

toSignal(

this.store.select(

selectAllCustomers

)

);

Template

@for(

customer of customers();

track customer.id

){

<div>

{{customer.name}}

</div>

}

Signals provide a clean reactive UI while Entity manages efficient collections.


Signals Architecture

flowchart LR

EntityStore

EntityStore --> Selector

Selector --> Signal

Signal --> Component

Enterprise Banking Example

A banking system stores:

  • Customers
  • Accounts
  • Cards
  • Loans
  • Investments
  • Transactions

Each collection contains thousands of records.

Architecture

flowchart TD

RESTAPI

RESTAPI --> EntityAdapter

EntityAdapter --> Store

Store --> EntitySelectors

EntitySelectors --> Signals

Signals --> Dashboard

Benefits

  • Fast lookups
  • Efficient updates
  • Minimal reducer code
  • Excellent scalability

Project Structure

store/

├── actions/
│
├── reducers/
│
├── selectors/
│
├── effects/
│
├── entity/
│
└── models/

Performance Best Practices

Practice Benefit
Use normalized state Faster lookups
Use EntityAdapter Less reducer code
Generate selectors Better performance
Use immutable updates Predictable state
Combine with Signals Cleaner UI
Use OnPush Faster rendering
Organize by feature Better scalability
Use sorting only when needed Lower processing cost

Common Mistakes

Managing Arrays Manually

❌ Wrong

customers.push(customer);

Use

adapter.addOne();

Ignoring Entity Selectors

Don't manually search arrays.

Use generated selectors.


Mutating State

Never modify Store state directly.

Always return immutable state using EntityAdapter methods.


Storing Duplicate Data

Keep one normalized collection.

Compute derived values using Selectors.


Using Entity for Tiny Collections

Entity shines with medium and large collections.

For very small local lists, plain arrays may be sufficient.


Array vs NgRx Entity

Feature Array NgRx Entity
CRUD Boilerplate High Very Low
Lookup Performance O(n) O(1) by ID lookup
Sorting Support Manual Built-in
Generated Selectors No Yes
Enterprise Applications Moderate Excellent

Advantages

Feature Benefit
EntityAdapter Less boilerplate
Normalized State Faster lookups
CRUD Helpers Cleaner reducers
Generated Selectors Less code
Signals Integration Modern Angular
Enterprise Ready Highly scalable

Top 10 NgRx Entity Interview Questions

1. What is NgRx Entity?

Answer

NgRx Entity is a library that simplifies managing collections in the NgRx Store using normalized state and helper methods for CRUD operations.


2. Why should we use NgRx Entity?

Answer

It reduces reducer boilerplate, improves lookup performance, provides generated selectors, and simplifies collection management.


3. What is EntityState?

Answer

EntityState<T> is an interface that stores entities in a normalized structure using an ids array and an entities dictionary.


4. What is an EntityAdapter?

Answer

An EntityAdapter is a helper object that provides methods such as addOne, addMany, updateOne, removeOne, setAll, and upsertOne.


5. What is normalized state?

Answer

Normalized state stores entities in a dictionary keyed by unique IDs, along with a separate list of IDs, avoiding duplicate data and enabling efficient lookups.


6. What selectors does Entity generate?

Answer

Entity automatically provides selectors including:

  • selectAll
  • selectEntities
  • selectIds
  • selectTotal

7. Can Entity be used with Signals?

Answer

Yes. Entity selectors can be converted into Signals using toSignal(), allowing Angular templates to consume normalized state reactively.


8. Can Entity sort data automatically?

Answer

Yes. An EntityAdapter can be configured with a sortComparer function to maintain sorted collections automatically.


9. What are common NgRx Entity mistakes?

Answer

  • Managing arrays manually
  • Ignoring generated selectors
  • Mutating state
  • Storing duplicate data
  • Using Entity where a simple array is sufficient

10. When should you use NgRx Entity?

Answer

Use NgRx Entity whenever your application manages medium or large collections with frequent CRUD operations, especially in enterprise applications.


Interview Cheat Sheet

Requirement Recommended Solution
Collection Management NgRx Entity
Normalized State EntityState
CRUD Operations EntityAdapter
Read Collections Generated Selectors
Reactive UI Signals
Change Detection OnPush
Async Data Effects
Global State Store
Enterprise Apps NgRx Entity + Store
Large Collections Entity + Selectors

Summary

NgRx Entity is one of the most valuable extensions to NgRx for managing collections efficiently. By storing data in a normalized format and providing an EntityAdapter with built-in CRUD operations and generated selectors, it significantly reduces boilerplate while improving performance and maintainability. Combined with Signals, Selectors, OnPush Change Detection, and Effects, NgRx Entity forms a robust foundation for scalable enterprise Angular applications.


Key Takeaways

  • ✅ NgRx Entity simplifies collection management.
  • EntityState stores normalized data using ids and entities.
  • EntityAdapter provides optimized CRUD operations.
  • ✅ Generated selectors reduce repetitive code.
  • ✅ Normalized state enables fast lookups by ID.
  • ✅ Use sortComparer for automatic sorting.
  • ✅ Integrate Entity selectors with Angular Signals.
  • ✅ Keep reducers immutable and concise.
  • ✅ Use Entity for medium and large collections.
  • ✅ NgRx Entity is a frequently asked enterprise Angular interview topic.

Next Article

➡️ 101-NgRx-ComponentStore-QA.md