Angular Signals CRUD step by step

Angular Signals CRUD step by step

Angular Signals is a versatile state management library designed to streamline communication between components and services within an Angular application. These signals act as getter functions that enable both the reading and writing of application state. When the value of a signal changes, all components subscribed to that signal are automatically notified, ensuring efficient state management across your application.

In this comprehensive guide, we will explore how to harness the power of Angular Signals to implement CRUD operations (Create, Read, Update, and Delete) in an Angular application, promoting clean and efficient code organization.

Step 1: Create Signals for Data Entities

The first crucial step in implementing CRUD operations with Angular Signals is to create signals for each data entity you intend to manage. For example, if you are developing a todo list application, you can create a signal specifically for todos:

import { signal } from '@angular/signals';

export const todos = signal<Todo[]>([]);

This signal serves as a centralized source of truth for your todos.

Step 2: Develop a Service for CRUD Operations

To interact with your data entities, create a service that provides methods for performing CRUD operations. In this example, we illustrate a TodoService that includes methods for creating, reading, updating, and deleting todos:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { todos } from './todos.signal';

@Injectable({
  providedIn: 'root'
})
export class TodoService {

  constructor() {}

  createTodo(todo: Todo): Observable<void> {
    return todos.update(todos => todos.push(todo));
  }

  readTodos(): Observable<Todo[]> {
    return todos;
  }

  updateTodo(todo: Todo): Observable<void> {
    return todos.update(todos => {
      const index = todos.findIndex(t => t.id === todo.id);
      todos[index] = todo;
      return todos;
    });
  }

  deleteTodo(todo: Todo): Observable<void> {
    return todos.update(todos => todos.filter(t => t.id !== todo.id));
  }
}

This service leverages the power of Angular Signals to handle CRUD operations efficiently.

Step 3: Inject the Service into Components

Inject the TodoService into the components that require access to the data entities. For instance, in a TodoListComponent, you can display a list of todos and allow users to create new ones:

import { Component, OnInit } from '@angular/core';
import { TodoService } from './todo.service';
import { Observable } from 'rxjs';
import { Todo } from './todo.model';

@Component({
  selector: 'app-todo-list',
  templateUrl: './todo-list.component.html',
  styleUrls: ['./todo-list.component.css']
})
export class TodoListComponent implements OnInit {

  todos$: Observable<Todo[]>;
  newTodoTitle: string;

  constructor(private todoService: TodoService) {}

  ngOnInit(): void {
    this.todos$ = this.todoService.readTodos();
  }

  createTodo(todo: Todo): void {
    this.todoService.createTodo(todo).subscribe();
  }
}

This component leverages the TodoService to retrieve and manipulate todos.

Step 4: Subscribe to Signals in Component Templates

In your component templates, you can subscribe to signals to display data and manage user interactions. Here's an example template that displays a list of todos and allows users to create new ones:

<ul>
  <li *ngFor="let todo of todos$ | async">

  </li>
</ul>

<input type="text" [(ngModel)]="newTodoTitle">
<button (click)="createTodo({ title: newTodoTitle })">Create Todo</button>

The (ngModel) directive binds user input to the newTodoTitle property, and the (click) event triggers the createTodo() method.

Step 5: Update Data in Service Methods

Finally, in the service methods, you can update the data entities within the signals. For instance, the createTodo() method adds a new todo to the todos signal:

createTodo(todo: Todo): Observable<void> {
  return todos.update(todos => todos.push(todo));
}

Upon calling this method, the todos signal is updated with the new todo, automatically notifying all subscribed components of the change.

The Benefits of Angular Signals in CRUD Operations

Angular Signals provide several advantages when employed in CRUD operations:

  1. Enhanced Performance Angular Signals optimize your application's performance by reducing the need for manual change detection cycles, resulting in a more responsive application.

  2. Improved Code Readability and Maintainability With Angular Signals, your code becomes more readable and maintainable. The elimination of manual subscriptions streamlines your logic and enhances code organization.

  3. Increased Reactivity Angular Signals empower you to write highly reactive code that efficiently responds to changes in state, ensuring a dynamic and user-friendly application.

Embrace Angular Signals for Effective State Management

If you are working with Angular 16 or later, consider incorporating Angular Signals into your application to simplify state management and streamline CRUD operations. Angular Signals offer a straightforward yet powerful solution to state management challenges, ultimately resulting in cleaner, more efficient code. Dive into Angular Signals today and witness the transformative impact they can have on your Angular application development journey.