# 19. Create feature state

## 1. Add state folder and attendee actions

The best place to start when adding a new slice of state and the associated reducer, effects, selectors and tests is with the action creators. Starting with action creators helps be clear about what you want this section to be able to do and like tests becomes self documenting.

* Create a state folder and a attendees sub-folder.
* Create a attendees.actions.ts file.
* Add the following actions to load attendees.

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

```typescript
import { Action } from '@ngrx/store';
import { Attendee } from '../../../models';

export enum AttendeesActionTypes {
  LoadAttendees = '[Attendees Page] Load Attendees',
  LoadAttendeesSuccess = '[Attendees Page] Load Attendees Success',
  LoadAttendeesFail = '[Attendees Page] Load Attendees Fail'
}

export class LoadAttendees implements Action {
  readonly type = AttendeesActionTypes.LoadAttendees;
}

export class LoadAttendeesSuccess implements Action {
  readonly type = AttendeesActionTypes.LoadAttendeesSuccess;
  constructor(public payload: Attendee[]) {}
}

export class LoadAttendeesFail implements Action {
  readonly type = AttendeesActionTypes.LoadAttendeesFail;
  constructor(public payload: any) {}
}

export type AttendeesActions =
  | LoadAttendees
  | LoadAttendeesSuccess
  | LoadAttendeesFail;
```

{% endcode %}

## 2. Create a attendees reducer

* Create a attendees.reducer.ts file in the state/attendees folder.
* Add a interface called State describing this slice of state.
* Add an initial state that implements this new State interface.
* Add a reducer function that uses our `initialState`, `AttendeesActionTypes` and `AttendeesActions` types. We will come back and talk about this when we do effects in the next section.

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

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

export interface State {
  attendees: Attendee[];
  loading: boolean;
}

export const intitalState: State = {
  attendees: [],
  loading: false
};

export function reducer(state = intitalState, action: AttendeesActions): State {
  switch (action.type) {
    case AttendeesActionTypes.LoadAttendees:
      {
      }

      break;

    default: {
      return state;
    }
  }
}

```

{% endcode %}

## 3. Add index.ts file to expose state logic from feature module

Index.ts files are like a public API for our feature state that re-exports everything we want to expose to our parts of our Angular application. Having an index.ts file helps other developers know what they should be able to access from this module.

In this index.ts file we will extend the feature State interface with our global State interface allowing us to have a more complete interface. We can not know what other lazy loaded state will have been loaded so this is not on the interface.

* Create a index.ts file inside the event/state folder.
* Import our global state name spaced to `fromRoot`.
* Import our attendee state name spaced as `fromAttendees`.
* Make a new `EventState` object that extends the root state.
* Make a `ActionReducerMap` that is a Map of all the reducers in this feature of which we have only one.

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

```typescript
import { ActionReducerMap } from '@ngrx/store';

import * as fromRoot from './../../state/state';
import * as fromAttendees from './attendees/attendees.reducer';

export interface EventState {
  attendees: fromAttendees.State;
}

export interface State extends fromRoot.State {
  event: EventState;
}

export const reducers: ActionReducerMap<EventState> = {
  attendees: fromAttendees.reducer
};

```

{% endcode %}

## 4. Register feature state in the EventModule

* Register `StoreModule.forFeature` in the `EventModule` and pass in our reducer map from the index.ts file.
* We need to name each piece of state even if it is a map of one or more reducers. This means our state tree will start with properties named after each feature state slice and one for each root state slice like below.

```javascript
{
    spinner: {...}
    event: {...}
    someOtherFeatureState: {...}
}
```

{% code title="src/app/event/event.module.ts" %}

```typescript
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api';

import { EventComponent } from './containers/event/event.component';
import { AddAttendeeComponent } from './components/add-attendee/add-attendee.component';
import { EventListComponent } from './components/event-list/event-list.component';
import { StoreModule } from '@ngrx/store';
import { reducers } from './state';
@NgModule({
  imports: [
    CommonModule,
    RouterModule.forChild([{ path: '', component: EventComponent }]),
    ReactiveFormsModule,
    HttpClientModule,
    StoreModule.forFeature('event', reducers)
  ],
  declarations: [EventComponent, AddAttendeeComponent, EventListComponent]
})
export class EventModule {}
```

{% endcode %}

## 5. Examine the state tree in the devtools

* Open browser and go to event page

![Event page of running app showing state tree with feature state](/files/-LMHe56JBWDnIWu6yrC_)

## StackBlitz Link

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://duncanhunter.gitbook.io/angular-and-ngrx/18.-create-feature-state.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
