The Complete Guide to CRUD Operations in Angular Using NgRx

Chintanonweb
Level Up Coding
Published in
4 min readSep 15, 2023

--

Introduction

In modern web development, building responsive and data-driven applications is crucial. Angular, a powerful and widely used JavaScript framework, provides the tools necessary to achieve this. When working with complex data management in Angular, NgRx is the go-to state management library. In this article, we’ll explore how to implement CRUD (Create, Read, Update, Delete) operations in Angular using NgRx, following the MECE (Mutually Exclusive, Collectively Exhaustive) principle for a well-organized and efficient codebase.

Table of Contents

  1. What is NgRx?
  2. Setting Up an Angular Project
  3. Creating the NgRx Store
  4. Implementing CRUD Operations
  5. Handling Asynchronous Actions
  6. Optimistic Updates for a Seamless User Experience
  7. FAQ Section
  8. Conclusion

What is NgRx?

NgRx is a state management library for Angular applications that is inspired by the Redux pattern. It helps manage the complex state of your application by providing a unidirectional data flow. This makes it easier to reason about how data changes over time and facilitates the maintenance of large-scale applications.

Setting Up an Angular Project

Before diving into NgRx and CRUD operations, let’s set up an Angular project. If you haven’t already installed Angular CLI, you can do so by running:

npm install -g @angular/cli

Once Angular CLI is installed, create a new Angular project:

ng new my-angular-app

Navigate to your project folder:

cd my-angular-app

Creating the NgRx Store

The heart of any NgRx application is the store, which holds the application’s state. To create a store, you’ll need to install NgRx packages:

ng add @ngrx/store

Now, let’s define the store structure by creating actions, reducers, and selectors.

Actions

Actions are plain JavaScript objects that represent unique events in your application. In a CRUD application, actions can be defined for creating, reading, updating, and deleting items. For instance:

export const createItem = createAction('[Items] Create Item', props<{ item: Item }>());
export const updateItem = createAction('[Items] Update Item', props<{ item: Item }>());
export const deleteItem = createAction('[Items] Delete Item', props<{ id: string }>());

Reducers

Reducers specify how the state should change in response to actions. They are pure functions that take the current state and an action as arguments and return a new state. Here’s a basic example:

const initialState: Item[] = [];

const itemsReducer = createReducer(
initialState,
on(createItem, (state, { item }) => [...state, item]),
on(updateItem, (state, { item }) => state.map(existingItem => existingItem.id === item.id ? item : existingItem)),
on(deleteItem, (state, { id }) => state.filter(item => item.id !== id))
);

Selectors

Selectors allow you to access specific pieces of state from the store. They help keep your components decoupled from the store structure. For example:

export const selectAllItems = createSelector(
(state: AppState) => state.items,
items => items
);

Implementing CRUD Operations

Now that we have our store set up, let’s implement CRUD operations in Angular.

Create Operation

To create an item, dispatch the createItem action:

this.store.dispatch(createItem({ item }));

Read Operation

Reading items is straightforward using selectors. In your component, select the items:

this.items$ = this.store.select(selectAllItems);

Update Operation

Updating an item involves dispatching the updateItem action:

this.store.dispatch(updateItem({ item }));

Delete Operation

To delete an item, dispatch the deleteItem action:

this.store.dispatch(deleteItem({ id }));

Handling Asynchronous Actions

In real-world applications, data often comes from APIs, making asynchronous actions essential. NgRx provides the @ngrx/effects library to handle side effects like API calls.

Effect for Fetching Data

Here’s an example of how to fetch data asynchronously using NgRx effects:

@Effect()
loadItems$ = this.actions$.pipe(
ofType(loadItems),
switchMap(() =>
this.itemService.getItems().pipe(
map(items => loadItemsSuccess({ items })),
catchError(error => of(loadItemsFailure({ error })))
)
)
);

Optimistic Updates for a Seamless User Experience

To enhance the user experience, you can implement optimistic updates. This means updating the UI immediately with the expected changes and then making the API call. If the API call fails, you can roll back the changes.

// Dispatch the optimistic update
this.store.dispatch(updateItem({ item: updatedItem }));

// Make the API call
this.itemService.updateItem(updatedItem).subscribe(
() => {
// API call successful
},
() => {
// API call failed, rollback the update
this.store.dispatch(updateItem({ item: previousItem }));
}
);

FAQ Section

Q1: Why use NgRx for state management in Angular?

A1: NgRx simplifies complex state management in Angular applications by providing a clear structure and a unidirectional data flow. It enhances code maintainability and scalability, making it an excellent choice for large-scale projects.

Q2: Can I use NgRx with Angular CLI-generated projects?

A2: Yes, you can integrate NgRx with Angular CLI-generated projects seamlessly. Angular CLI provides commands for adding NgRx-related packages and generating boilerplate code.

Q3: Are there any alternatives to NgRx for state management in Angular?

A3: Yes, there are alternatives like ngx-store and ngxs. However, NgRx is the most widely used and has strong community and ecosystem support.

Conclusion

In this comprehensive guide, we’ve explored how to implement CRUD operations in Angular using NgRx. We’ve covered the setup of NgRx, actions, reducers, selectors, and handling asynchronous actions with effects. Additionally, we’ve discussed the concept of optimistic updates to provide a smoother user experience. By following these guidelines and the MECE principle, you’ll be well-equipped to build efficient and maintainable Angular applications with NgRx. Happy coding!

--

--

As a software engineer, bringing my ideas to life through code and inspiring others with the possibilities. Managed By : chintandhokai97@gmail.com