avatarAtakan Korez

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

3557

Abstract

and</span>: <span class="hljs-built_in">string</span>; <span class="hljs-attr">model</span>: <span class="hljs-built_in">string</span>; <span class="hljs-attr">isElectric</span>: <span class="hljs-built_in">boolean</span> }[]> = <span class="hljs-title function_">signal</span>([]);

<span class="hljs-title function_">addVehicle</span>(<span class="hljs-params">model: <span class="hljs-built_in">string</span>, year: <span class="hljs-built_in">number</span>, isElectric: <span class="hljs-built_in">boolean</span></span>) { <span class="hljs-variable language_">this</span>.<span class="hljs-property">vehicles</span>.<span class="hljs-title function_">mutate</span>(<span class="hljs-function">(<span class="hljs-params">data</span>) =></span> data.<span class="hljs-title function_">push</span>({ <span class="hljs-attr">brand</span>: brand, <span class="hljs-attr">model</span>: model, <span class="hljs-attr">isElectric</span>: isElectric, }) ); }

<span class="hljs-title function_">getAllVehicles</span>(<span class="hljs-params"></span>) { <span class="hljs-keyword">return</span> <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">vehicles</span>(); } }</pre></div><p id="d8ed">If you take a look at the above example, in the 9th line, the collection within the signal named <code>vehicles</code> has the vehicle object with the <b>brand</b> and <b>model </b>information added in <code>addVehicle</code> method, and in the <code>getAllVehicles</code> method, the collection, which is the value of this signal, is returned.</p><p id="c151">Now, let’s look at the components that will use this service — <i>createVehicle </i>and <i>listVehicle</i>:</p><div id="104e"><pre><span class="hljs-keyword">import</span> { Component, inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>; <span class="hljs-keyword">import</span> { CommonModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common'</span>; <span class="hljs-keyword">import</span> { VehicleStateManagementService} <span class="hljs-keyword">from</span> <span class="hljs-string">'src/app/services/vehicle-state-management.service'</span>;

<span class="hljs-meta">@Component(<span class="hljs-params">{ selector: <span class="hljs-string">'app-create-vehicle'</span>, standalone: true, imports: [CommonModule], template: &lt;<span class="hljs-built_in">input</span> <span class="hljs-built_in">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-comment">#txtBrand placeholder="Brand"&gt; &lt;br&gt;</span> &lt;<span class="hljs-built_in">input</span> <span class="hljs-built_in">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-comment">#txtModel placeholder="Model"&gt; &lt;br&gt;</span> &lt;<span class="hljs-built_in">input</span> <span class="hljs-built_in">type</span>=<span class="hljs-string">"checkbox"</span> <span class="hljs-comment">#chkIsElectric placeholder="IsElectric"&gt; &lt;br&gt;</span> &lt;button (<span class="hljs-params">click</span>)=<span class="hljs-string">"createVehicle(txtBrand.value, txtModel.value, chkIsElectric.value)"</span>&gt;Create Vehicle&lt;/button&gt; , }</span>)</span> export <span class="hljs-keyword">class</span> <span class="hljs-title class_">CreateVehicleComponent</span> { vehicleStateManagementService: VehicleStateManagementService = inject(VehicleStateManagementService); createVehicle(brand

Options

: string, model: string, isElectric:boolean) { this.vehicleStateManagementService.createVehicle(model, name, isElectric); } }</pre></div><div id="7fb6"><pre><span class="hljs-keyword">import</span> { <span class="hljs-title class_">Component</span>, <span class="hljs-title class_">OnInit</span>, inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>; <span class="hljs-keyword">import</span> { <span class="hljs-title class_">CommonModule</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common'</span>; <span class="hljs-keyword">import</span> { <span class="hljs-title class_">VehicleStateManagementService</span>} <span class="hljs-keyword">from</span> <span class="hljs-string">'src/app/services/vehicle-state-management.service'</span>;

<span class="hljs-meta">@Component</span>({ <span class="hljs-attr">selector</span>: <span class="hljs-string">'app-list-vehicle'</span>, <span class="hljs-attr">standalone</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">imports</span>: [<span class="hljs-title class_">CommonModule</span>], <span class="hljs-attr">template</span>: <span class="hljs-string"> &lt;ul&gt; &lt;li *ngFor="let vehicle of vehicles"&gt;Brand:{{vehicle.brand}}, Model: {{vehicle.model}}, ElectrictyCar:{vehicle.isElectric}} &lt;/li&gt; &lt;/ul&gt; </span>, }) <span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ListVehicleComponent</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">OnInit</span> { <span class="hljs-attr">vehicleStateManagementService</span>: <span class="hljs-title class_">VehicleStateManagementService</span>= <span class="hljs-title function_">inject</span>(<span class="hljs-title class_">VehicleStateManagementService</span>);

<span class="hljs-attr">vehicles</span>: { <span class="hljs-attr">brand</span>: <span class="hljs-built_in">string</span>, <span class="hljs-attr">model</span>: <span class="hljs-built_in">string</span>, <span class="hljs-attr">brand</span>: <span class="hljs-built_in">boolean</span>}[]; <span class="hljs-title function_">ngOnInit</span>(<span class="hljs-params"></span>) { <span class="hljs-variable language_">this</span>.<span class="hljs-property">vehicles</span> = <span class="hljs-variable language_">this</span>.<span class="hljs-property">VehicleStateManagementService</span>.<span class="hljs-title function_">getVehicles</span>() } }</pre></div><p id="0eb4">As seen below components, the vehicle information added in the <i>CreateVehicleComponent </i>is dynamically transferred to the <i>ListVehicleComponent </i>through the signal-based service. In other words, the changes resulting from adding a vehicle are instantly reflected in the component responsible for listing.</p><h2 id="ab5c">Conclusion</h2><p id="7fc3">In this blog, I have demonstrated how state management in Angular applications can be handled with <i>Signals </i>without using any third-party libraries. I particularly emphasized that this approach allows for a simple and straightforward way of managing this process, especially in large projects.</p><p id="284b">By reducing complexity, this approach enables projects to be developed more effectively and efficiently. I hope you consider using this method in your future projects.</p><p id="e3f2"><i>If you found this blog post helpful, please give it a clap. Thanks for reading…</i></p></article></body>

Easy and effective State Management for Angular with Signals

In this blog, we will delve into a simple and effective State Management technique using the novel Signals architecture introduced in Angular 16. (You can access my blog post, in which I examine the Angular Signals structure in depth → Link)

While Angular’s architecture is inherently rule-based and might seem complex, grasping its core logic reveals a developer-friendly structure. However, when it comes to state management within this seemingly intricate architecture, complexity can inevitably arise. In larger projects, achieving efficient state management calls for a commitment to the principle of simplicity. A pragmatic approach involves focusing solely on managing essential states and avoiding unnecessary intricacies.

To achieve this, leveraging existing libraries like NgRx, Akita, and MobX is an option. However, a recent consensus suggests that, to sidestep the complexities and boilerplate structures introduced by these libraries, a more viable approach may involve utilizing Angular’s injectable services without relying on additional frameworks. This preference is grounded in the reactive nature of injectable services, their provision of initial values, and their ease of writing, development, and maintenance.

Understanding state management terminology like actions, reducers, etc., may not be necessary for projects of any size. Also, NgRx’s use of BehaviorSubject introduces below challenges:

  1. Requires strong RxJS knowledge.
  2. This may lead to excessive memory consumption and leaks in long or large data streams.
  3. Synchronization or reliability issues in scenarios with multiple threads or asynchronous processes.

Considering these, a signal-based architecture offers optimized change detection and synchronization. Choosing this approach, with the ability to snapshot values instantly, could be preferred in state management. Simply design a store using the signal concept, as demonstrated in a scenario where vehicle information entered in one component is listed in another.

VehicleStateManagementService:

import { Injectable, WritableSignal, signal } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class VehicleStateManagementService {
  constructor() {}
  private vehicles: WritableSignal<{ brand: string; model: string; isElectric: boolean }[]> = signal([]);

  addVehicle(model: string, year: number, isElectric: boolean) {
    this.vehicles.mutate((data) =>
      data.push({
        brand: brand,
        model: model,
        isElectric: isElectric,
      })
    );
  }

  getAllVehicles() {
    return this.vehicles();
  }
}

If you take a look at the above example, in the 9th line, the collection within the signal named vehicles has the vehicle object with the brand and model information added in addVehicle method, and in the getAllVehicles method, the collection, which is the value of this signal, is returned.

Now, let’s look at the components that will use this service — createVehicle and listVehicle:

import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { VehicleStateManagementService} from 'src/app/services/vehicle-state-management.service';
 
@Component({
  selector: 'app-create-vehicle',
  standalone: true,
  imports: [CommonModule],
  template: `
    <input type="text" #txtBrand placeholder="Brand"> <br>
    <input type="text" #txtModel placeholder="Model"> <br>
    <input type="checkbox" #chkIsElectric placeholder="IsElectric"> <br>
    <button (click)="createVehicle(txtBrand.value, txtModel.value, chkIsElectric.value)">Create Vehicle</button>
  `,
})
export class CreateVehicleComponent {
  vehicleStateManagementService: VehicleStateManagementService = inject(VehicleStateManagementService);
  createVehicle(brand: string, model: string, isElectric:boolean) {
    this.vehicleStateManagementService.createVehicle(model, name, isElectric);
  }
}
import { Component, OnInit, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { VehicleStateManagementService} from 'src/app/services/vehicle-state-management.service';
 
@Component({
  selector: 'app-list-vehicle',
  standalone: true,
  imports: [CommonModule],
  template: `
    <ul>
      <li *ngFor="let vehicle of vehicles">Brand:{{vehicle.brand}}, Model: {{vehicle.model}}, ElectrictyCar:{vehicle.isElectric}} </li>
    </ul>
  `,
})
export class ListVehicleComponent implements OnInit {
  vehicleStateManagementService: VehicleStateManagementService= inject(VehicleStateManagementService);
 
 
  vehicles: { brand: string, model: string, brand: boolean}[];
  ngOnInit() {
    this.vehicles = this.VehicleStateManagementService.getVehicles()
  }
}

As seen below components, the vehicle information added in the CreateVehicleComponent is dynamically transferred to the ListVehicleComponent through the signal-based service. In other words, the changes resulting from adding a vehicle are instantly reflected in the component responsible for listing.

Conclusion

In this blog, I have demonstrated how state management in Angular applications can be handled with Signals without using any third-party libraries. I particularly emphasized that this approach allows for a simple and straightforward way of managing this process, especially in large projects.

By reducing complexity, this approach enables projects to be developed more effectively and efficiently. I hope you consider using this method in your future projects.

If you found this blog post helpful, please give it a clap. Thanks for reading…

Angular 17
State Management
Angular Development
Rxjs
Angular
Recommended from ReadMedium