> For the complete documentation index, see [llms.txt](https://duncanhunter.gitbook.io/angular-and-ngrx/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://duncanhunter.gitbook.io/angular-and-ngrx/22.-use-entity-adapter.md).

# 22. Use Entity Adapter

## 1. npm install @ngrx/entity

Entity State adapter for managing record collections. @ngrx/entity provides an API to manipulate and query entity collections.

1. Reduces boilerplate for creating reducers that manage a collection of models.
2. Provides performant CRUD operations for managing entity collections.
3. Extensible type-safe adapters for selecting entity information.

* npm install the library

```
npm i @ngrx/entity
```

## 2. Make an entity adapter&#x20;

* make an adapter and use it to make the initial state and manage collections.

{% code title="src/app/event/state/attendees/attendees.reducer.ts" %}

```typescript
<---------- ABBREVIATED CODE SNIPPET ---------->

import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';

import { AttendeesActions, AttendeesActionTypes } from './attendees.actions';
import { Attendee } from '../../../models';

export interface State extends EntityState<Attendee> {
  loading: boolean;
  error: any;
}

const adapter: EntityAdapter<Attendee> = createEntityAdapter<Attendee>();

export const intitalState: State = adapter.getInitialState({
  loading: false,
  error: null
});

export function reducer(state = intitalState, action: AttendeesActions): State {

<---------- ABBREVIATED CODE SNIPPET ---------->

```

{% endcode %}

## 3. Update reducer to use entity adapter collection methods

The entity adapter will allow us to take a collection and manage it with a set of Adapter Collection Methods. The entity adapter also provides methods for operations against an entity. These methods can change one to many records at a time. Each method returns the newly modified state if changes were made and the same state if no changes were made. You can read more here <https://github.com/ngrx/platform/blob/master/docs/entity/adapter.md>.

| Method     | Action                                              |
| ---------- | --------------------------------------------------- |
| addOne     | Add one entity to the collection                    |
| addMany    | Add multiple entities to the collection             |
| addAll     | Replace current collection with provided collection |
| removeOne  | Remove one entity from the collection               |
| removeAll  | Clear entity collection                             |
| updateOne  | Update one entity in the collectionaddOne           |
| updateMany | Update multiple entities in the collection          |
| upsertOne  | Add or Update one entity in the collection          |
| upsertMany | Add or Update multiple entities in the collection   |

* Change out manual collection management for adapter collection methods.
* Make selectors from the adapter with `adapter.getSelectors` method.

{% code title="src/app/event/state/attendees/attendees.reducer.ts" %}

```typescript
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';

import { AttendeesActions, AttendeesActionTypes } from './attendees.actions';
import { Attendee } from '../../../models';

export interface State extends EntityState<Attendee> {
  loading: boolean;
  error: any;
}

const adapter: EntityAdapter<Attendee> = createEntityAdapter<Attendee>();

export const intitalState: State = adapter.getInitialState({
  loading: false,
  error: null
});

export function reducer(state = intitalState, action: AttendeesActions): State {
  switch (action.type) {
    case AttendeesActionTypes.LoadAttendees: {
      return adapter.removeAll({
        ...state,
        loading: false,
        error: null
      });
    }

    case AttendeesActionTypes.LoadAttendeesSuccess: {
      return adapter.addAll(action.payload, {
        ...state,
        loading: false,
        error: null
      });
    }

    case AttendeesActionTypes.LoadAttendeesFail: {
      return adapter.removeAll({
        ...state,
        loading: false,
        error: action.payload
      });
    }

    default: {
      return state;
    }
  }
}

export const {
  selectIds,
  selectEntities,
  selectAll,
  selectTotal
} = adapter.getSelectors();


```

{% endcode %}

## 3. Update selectors

* Update attendee selectors to use the new adapter getSelector methods.

{% code title="src/app/event/state/attendees/attendees.selectors.ts" %}

```typescript
import { createFeatureSelector, createSelector } from '@ngrx/store';
import * as fromAttendee from './../attendees/attendees.reducer';
import { EventState } from '..';

export const getEventState = createFeatureSelector<EventState>('event');
export const getAttendeeState = createSelector(
  getEventState,
  state => state.attendees
);

export const getAttendees = createSelector(
  getAttendeeState,
  fromAttendee.selectAll
);

```

{% endcode %}

![Entity adapter making new ids and entities dictionaries.](/files/-LMI9DX6Bgfz4a1ZGDlp)

## StackBlitz Link

{% embed url="<https://stackblitz.com/github/duncanhunter/angular-and-ngrx-demo-app/tree/22-add-entity-adapter>" %}
Web Link: Link to the demo app running in StackBlitz
{% endembed %}
