Signal Input is now available in developer preview for Angular devs | by Paul Gschwendtner | Feb, 2024
[ad_1]
In Angular 17.1 we introduced signal-based inputs as a reactive alternative to decorator-based @Input()
.
The new inputs provide developers with new ways that:
- allow you to integrate and benefit from Angular signals today:
▹ providing easier ways to run logic whenever an input changes.
▹ efficient solutions for deriving state from inputs.
▹ enabling a smoother experience withOnPush
and future Zoneless. - improve code quality and developer productivity by increasing type safety of inputs.
Those are available in developer preview and we would like your feedback!
As with @Input
, signal inputs allow values to be bound from parent components. A key difference with signal inputs is that these values are exposed using a Signal
and can change during the lifecycle of your component.
Now, developers can leverage the power of signals to respond effectively to these potential changes in a reactive way. Angular supports two variants of signal inputs.
- Optional inputs — Inputs are optional by default. You can specify an explicit initial value, or Angular will use
undefined
implicitly as the initial value. - Required inputs — Required inputs always have a value of the given input type. There can be no initial value, and required inputs are declared using the
input.required
function.
An input is automatically recognized by Angular whenever you use the input or input.required functions as initializer of class members. The following demonstrates how you can declare signal inputs in your application:
import {Component, input} from '@angular/core';@Component({…})
export class MyComp {
// optional inputs
firstName = input<string>();
age = input(0);
// required inputs
lastName = input.required<string>();
}
After they are defined, you can use them in your templates with the same syntax as other signals:
<p>First name: {{firstName()}}</p>
<p>Last name: {{lastName()}}</p>
Find out more in the dedicated guide for signal inputs. https://angular.io/guide/signal-inputs.
In comparison to decorator-based @Input
, signal inputs provide numerous benefits:
- Signal inputs, when used in templates, will automatically mark OnPush components as dirty.
▹ This improves code quality and developer experience (DX), and is paving the way for Zoneless - Signal inputs are more type safe:
▹ Unlike today, required inputs do not require initial values, or other tricks to satisfy TypeScript.
▹ Transforms are type-checked to match the accepted input values. - Values can be easily derived whenever an input changes using a
computed
, like with other signals. - Easier and more local monitoring of inputs using
effect
instead ofngOnChanges
or setters.
The Angular team recommendation is to use signal inputs once they are out of developer preview and promoted to production ready in an upcoming version.
Signals provide a powerful reactivity model that enables you to efficiently monitor changes, derive values, while automatically notifying Angular whenever specific parts of your application need to be re-rendered. This makes it easier and safer to build performant applications that only refresh the parts that actually changed.
Below we are highlighting some potential use-cases.
This example demonstrates how you can declare a signal input for a component and display its value.
import {input} from '@angular/core';@Component({
// …
template: `Your name is: {{yourName()}}`,
})
class HelloComponent {
yourName = input.required<string>();
}
This example watches changes to a firstName
input and uses effect()
to react to those changes:
import {input, effect} from '@angular/core';class MyComp {
firstName = input.required<string>();
constructor() {
effect(() => {
// will be called when `firstName` is initialized or changes.
console.log(this.firstName());
});
}
}
You can efficiently derive values based on signal inputs by using computed
. Signal inputs can be used in a computed
like any other signal in your application.
In the following example, we derive a value from an input called age
. Whenever age
changes, the ageMultiplied
field will be notified and can re-run to multiply the age by two. On the other hand, if age
does not change, the ageMultiplied
derivation will efficiently use the previous memoized value without executing.
import {Component, input, computed} from '@angular/core';@Component({…})
export class MyComp {
age = input(0);
// age multiplied by two.
ageMultiplied = computed(() => this.age() * 2);
}
Signal inputs support the same features as decorator-based inputs. You can specify a transform function for a signal input to parse raw values to your expected input type.
Note that value transforms should never change the meaning of an input. More information on this in the new guide on angular.dev — https://angular.io/guide/signal-inputs#value-transforms
export class MyCheckboxComponent {
disabled = input(false, {
// supports `<my-checkbox disabled="" />` as a shorthand
transform: (v: boolean|string) => typeof v === 'string' ? v === '' : v,
});
}
You can also do things, like aliasing an input to meet your needs:
export class StudentDirective {
age = input(0, {alias: 'studentAge'});
}
We’re overjoyed to bring this feature to the Angular community in developer preview. Signal inputs can be used today, and are production ready. Developer preview allows us to make changes in response to feedback that we receive from the community.
With that in mind, we’d love your feedback as we continue to stabilize signal inputs. There were a few complicated trade-offs and other questions for upcoming APIs:
- The shorthand for
input<string>()
may be confusing as the input implicitly uses undefined as initial value.
— Is this confusing because the generic just showsstring
?
— We believe the shorthand is useful as we saw the majority of inputs usingundefined
as initial value inside the Google codebase. - Inputs are now read-only.
— Previously with@Input
, you were able to desynchronize the input by updating from within the component.
— Is this affecting your application? If you intend to update the input, please consider usingmodel()
and exposing the updated state to your component to consumers. Why does this not work for you?
Your feedback is valuable and we look forward to hearing from you. If you have feedback, consider letting us know in the comments, on GitHub or X.
Be sure to try out signal inputs today by installing the latest version of Angular with ng update
.
Thanks and keep us updated!
[ad_2]
Source link