javascriptangulartypescriptimmutabilityangular-signals

How to delete an item in an immutable signal array or a key/value in a signal object?


To update items into an immutable array, we can easily do:

array = signal([1,2,3]);
...

...
this.array.update(item => [ ...item, 'newItem' ]);

To update items into an immutable object easily do:

object = signal({});
...

...
this.object.update(obj => ({ ...obj, key :'newValue' }))

But how to delete some items of an array. Also please refer to demo@stackblitz


Solution

  • For Array:

    Assuming, we want to delete an array of values, we can use filter array method to filter out the values that present in the delete array.

    There is no need for array destructuring because filter will already return a new memory instance

      delItem() {
        const itemsToDelete = [2];
        const keysToDelete = ['key1'];
        // how to delete items into the arr and obj immutable?
        this.arr.update((item) => {
          // splice by index
          const filteredItems = item.filter((x) => !itemsToDelete.includes(x));
          return filteredItems;
        });
        ...
    

    For Objects:

    Using plain JS:

      delItem() {
        ...
        // using plain JS
        this.obj.update((obj) => {
          keysToDelete.forEach((key: string) => {
            delete obj[key];
          });
          return { ...obj };
        });
      }
    

    Using Lodash:

    We can use the omit method from lodash-es to remove the unwanted properties.

    We need to install lodash-es using the below commands.

    npm i lodash-es
    npm i --save-dev @types/lodash-es
    

    The code will be like below:

      delItem() {
        ...
        // using lodash omit
        this.obj.update((obj) => ({ ...omit(obj, ['key1']) }));
        ...
      }
    

    Full Code:

    import { Component, signal } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import { FormsModule } from '@angular/forms';
    import { JsonPipe } from '@angular/common';
    import { omit } from 'lodash-es';
    
    @Component({
      selector: 'app-root',
      imports: [FormsModule, JsonPipe],
      template: `
        <h1> {{ name }}!</h1>
        existing <br>
        
       arr: {{arr() | json}}<br>
       obj:  {{obj() | json}}<br>
       <br>
        <button (click)=delItem()>delete Items</button>
        <br>
        <br>
        <button (click)=AddItem()>Add Items</button>
      `,
    })
    export class App {
      name =
        'How to delete an item into a immutabe  signal array or  key/value in  signal object?';
      arr = signal([1, 2, 3]);
      obj = signal({ key1: 'Value1', key2: 'Value2' });
    
      AddItem() {
        this.arr.update((item) => [...item, 5]);
        this.obj.update((obj) => ({ ...obj, key: 'newValue' }));
      }
    
      delItem() {
        const itemsToDelete = [2];
        const keysToDelete = ['key1'];
        // how to delete items into the arr and obj immutable?
        this.arr.update((item) => {
          // splice by index
          const filteredItems = item.filter((x) => !itemsToDelete.includes(x));
          return filteredItems;
        });
        // using lodash omit
        // this.obj.update((obj) => ({ ...omit(obj, ['key1']) }));
        // using plain JS
        this.obj.update((obj: any) => {
          keysToDelete.forEach((key: string) => {
            delete obj[key];
          });
          return { ...obj };
        });
      }
    }
    
    bootstrapApplication(App);
    

    Stackblitz Demo