Search code examples
javascriptangulartypescriptsignalsangular-signals

How to Use transform to Convert an @Input Array to an Object in Angular?


Can I use transform to have an @Input or InputSignal receive an array and transform it to an object containing the array?

Example:

<my-component
    [array]="myArray"
/>


export class MyComponent {
    public readonly array = input<number[]>([], {
            transform: transformArrayToObject,
        });

So if the value passed to array is [1, 2, 3], the transformed data will be, by example:

{
  array: [1, 2, 3];
  status: Status.OK
}

Solution

  • Transform is usually good for modifying a source type and returning the same type with manipulations to the inner values. If you want to create a new object, it's better to use computed which will create a new object based on the original signal. The computed signal will refresh whenever the source signal changes.

    ...
    export class Child {
      public readonly value: InputSignal<any[]> = input<any[]>([]);
      public readonly computedValue = computed(() => ({
        status: Status.OK,
        data: this.value(),
      }));
    }
    

    Full Code:

    import { CommonModule } from '@angular/common';
    import { Component, InputSignal, computed, input } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import 'zone.js';
    
    export enum Status {
      OK,
    }
    
    export interface DataObject {
      status: number;
      data: any[];
    }
    
    @Component({
      selector: 'app-child',
      imports: [CommonModule],
      standalone: true,
      template: `{{computedValue() | json}}`,
    })
    export class Child {
      public readonly value: InputSignal<any[]> = input<any[]>([]);
      public readonly computedValue = computed(() => ({
        status: Status.OK,
        data: this.value(),
      }));
    }
    
    @Component({
      selector: 'app-root',
      standalone: true,
      imports: [Child],
      template: `
        <app-child [value]="[1,2,3,4,100]"/>
      `,
    })
    export class App {
      name = 'Angular';
    }
    
    bootstrapApplication(App);
    

    Stackblitz Demo