• Skip to primary navigation
  • Skip to main content
  • Skip to footer

Codemotion Magazine

We code the future. Together

  • Discover
    • Events
    • Community
    • Partners
    • Become a partner
    • Hackathons
  • Magazine
    • Backend
    • Dev community
    • Carriere tech
    • Intelligenza artificiale
    • Interviste
    • Frontend
    • DevOps/Cloud
    • Linguaggi di programmazione
    • Soft Skill
  • Talent
    • Discover Talent
    • Jobs
    • Manifesto
  • Companies
  • For Business
    • EN
    • IT
    • ES
  • Sign in

Davide PassafaroFebbraio 7, 2024

Angular Signal Inputs: verso i Signal Components

Frontend
angular signal components
facebooktwitterlinkedinreddit

L’introduzione dei Signal Inputs è il primo passo verso i Signal Components e le applicazioni Angular zoneless, introduzione che migliora fin da subito la qualità del nostro codice e l’esperienza di sviluppo. In questo articolo vedremo come utilizzarli.

⚠️ ATTENZIONE: i Signal Inputs sono ancora ufficialmente in developer preview ⚠️

Recommended article
Maggio 6, 2025

Top 10 Web Hosting Service gratuiti che tutti i dev devono conoscere

Lucilla Tomassi

Lucilla Tomassi

Frontend

Ciao ciao @Input( ); Benvenuta funzione input( )

Creare un Signal Input è piuttosto semplice:
invece di creare un input utilizzando il decoratore @Input( ), dobbiamo utilizzare la funzione input( ) fornita da @angular/core.

Ecco un esempio di come possiamo creare un input di tipo stringa:

import { Component, input } from '@angular/core';

@Component({ ... })
  export class MyComponent {
  myProp = input<string>();
}
Code language: TypeScript (typescript)

Utilizzando la funzione input( ) i nostri input vengono creati di tipo InputSignal, uno speciale tipo di Signal read-only definito cosi:

* Un InputSignal è simile ad un signal non-writable tranne che porta con se informazioni addizionali sulla tipizzazione per la proprietà transform, e che Angular aggiorna internamente il signal quando un nuovo valore viene fornito.

Più precisamente i nostri Signal Inputs sono di questo tipo:

myProp: InputSignal<ReadT, WriteT = ReadT> = input<ReadT>(...)
Code language: TypeScript (typescript)

Dove ReadT rappresenta il tipo del valore del signal e WriteT invece il tipo del valore atteso dal componente padre.
Seppure questi due tipi spesso coincidono, approfondiremo il loro ruolo e le differenze tra essi quando parleremo della funzione transform più avanti.

Torniamo ora all’esempio precedente concentrandoci sul tipo del nostro input:

import { Component, InputSignal, input } from '@angular/core';

@Component({ ... })
  export class MyComponent {
  myProp: InputSignal<string | undefined, string | undefined> = input<string>();
}
Code language: TypeScript (typescript)

Quegli undefined sono risultanti dalla natura opzionale del valore dell’input.

Per specificare che un input è required, e sbarazzarci quindi di quei fastidiosi undefined, la nuova input api ci offre una apposita funzione required( ):

import { Component, InputSignal, input } from '@angular/core';

@Component({ ... })
  export class MyComponent {
  myProp: InputSignal<string, string> = input.required<string>();
}
Code language: TypeScript (typescript)

In alternativa, possiamo fornire un valore di default alla funzione input( ):

import { Component, InputSignal, input } from '@angular/core';

@Component({ ... })
  export class MyComponent {
  myProp: InputSignal<string, string> = input<string>('');
}
Code language: TypeScript (typescript)

Allo stesso modo, il valore di default può essere fornito anche alla funzione required( ).



Leggi anche: Angular Control Flow, la guida completa


Niente più ngOnChanges( )

Al giorno d’oggi è molto comune utilizzare ngOnChanges o funzioni setter per svolgere azioni quando un determinato input viene aggiornato.

Con i Signal Inputs, possiamo sfruttare a pieno la potenza dei Signals e sbarazzarci di queste funzioni grazie a due funzionalità: computed ed effect.

Computed Signals

Utilizzando la funzione computed possiamo definire valori derivati a partire da altri input, uno o più, che saranno sempre sincronizzati mano a mano che i valori vengono aggiornati:

import { Component, InputSignal, Signal, computed, input } from '@angular/core';

@Component({ ... })
export class MyComponent {
  description: InputSignal<string, string> = input<string>('');
  descriptionLength: Signal<number> = computed(() => this.description.length);
}
Code language: TypeScript (typescript)

Dunque ogni volta che l’input description viene modificato, dall’interno e dall’esterno, il valore di descriptionLength viene ricalcolato e aggiornato di conseguenza.

Effect

Con la funzione effect, possiamo invece definire side effects che vengano eseguiti quando i nostri input, uno o più, vengono aggiornati.

Per esempio, immaginiamo di dover aggiornare una entità proveniente da uno script third-party, che stiamo usando per creare un grafico a barre, quando un input viene aggiornato:

import Chart from 'third-party-charts';
import { effect, Component, InputSignal, input } from '@angular/core';

@Component({ ... })
export class MyComponent {
  chartData: InputSignal<string[], string[]> = input.required<string[]>();

  constructor() {
    const chart = new Chart({ ... });

    effect((onCleanup) => {
      chart.updateData(this.chartData());

      onCleanup(() => {
        chart.destroy();
      });
    });
  }
}
Code language: TypeScript (typescript)

Oppure di dover effettuare una richiesta http:

import { HttpClient } from '@angular/common/http';
import { effect, Component, InputSignal, inject, input } from '@angular/core';

@Component({ ... })
export class MyComponent {
  myId: InputSignal<string, string> = input.required<string>();

  response: string = '';

  constructor() {
    const httpClient = inject(HttpClient);

    effect((onCleanup) => {
      const sub = httpClient.get<string>(`myurl/${this.myId()}/`)
        .subscribe((resp) => { this.response = resp });

      onCleanup(() => {
        sub.unsubscribe();
      });
    });
  }
}
Code language: TypeScript (typescript)

Utilizzare computed ed effect rende i nostri componenti più robusti e ottimizzati, migliorando inoltre di molto la manutenibilità del nostro codice.


Alias e funzione transform

Per garantire una migrazione degli input creati con @Input( ) più semplice, i Signal Inputs supportano anche la proprietà alias e la funzione transform:

import { HttpClient } from '@angular/common/http';
import { effect, Component, InputSignal, inject, input } from '@angular/core';

@Component({ ... })
export class MyComponent {
  textLength: InputSignal<number, string> = input<number, string>(0, {
    alias: 'descriptionText',
    transform: (text) => text.length
  });
}
Code language: TypeScript (typescript)

In particolare, grazie alla funzione transform possiamo definire una funzione per manipolare il valore del nostro input prima che sia disponibile all’interno del componente, ed è proprio qui che entrano in gioco ReadT e WriteT.

Infatti, utilizzare la funzione transform può portare ad una differenza tra il tipo del valore fornito dal componente padre, rappresentato WriteT, e il tipo del valore all’interno del nostro Signal Input, rappresentato da ReadT.

Per questo motivo, quando creiamo un Signal Input con la funzione transform possiamo specificare entrambi i valori di ReadT e WriteT come type arguments della funzione:

mySimpleProp: InputSignal<ReadT, WriteT = ReadT> = input<ReadT>(...)

myTransformedProp: InputSignal<ReadT, WriteT> = input<ReadT, WriteT>( ... , {
  transform: transformFunction
});
Code language: TypeScript (typescript)

Senza la funzione transform il valore di WriteT è valorizzato identico a ReadT, mentre utilizzando la funzione transform sia ReadT che WriteT sono definiti distintamente.


E per quanto riguarda il two-way binding?

Al momento non è possibile implementare il two-way binding con i Signal Inputs, ma in futuro verrà esposta una nuova api chiamata Model Input che fornirà una funzione set( ).

Stay tuned!!!


Grazie per aver letto questo articolo 🙏

Mi piacerebbe avere qualche feedback quindi grazie in anticipo per qualsiasi commento. 👋

Un ringraziamento speciale a  Paul Gschwendtner ed a tutto il Team Angular per questa funzionalità.

Codemotion Collection Background
Dalla community
Selezionati per te

Vuoi scoprire più articoli come questo? Dai un’occhiata alla collection Dalla community dove troverai sempre nuovi contenuti selezionati dal nostro team.

Share on:facebooktwitterlinkedinreddit

Tagged as:Angular

Davide Passafaro
5 migliori database open source nel 2024
Previous Post
Si può continuare a scrivere codice essendo CTO?
Next Post

Footer

Discover

  • Events
  • Community
  • Partners
  • Become a partner
  • Hackathons

Magazine

  • Tech articles

Talent

  • Discover talent
  • Jobs

Companies

  • Discover companies

For Business

  • Codemotion for companies

About

  • About us
  • Become a contributor
  • Work with us
  • Contact us

Follow Us

© Copyright Codemotion srl Via Marsala, 29/H, 00185 Roma P.IVA 12392791005 | Privacy policy | Terms and conditions