I am refactoring my angular code to work with signals. I have this below code, which needs to be refactored.
@Component({ ... })
export class SomeComponent {
@Input() test = null;
ngOnInit() {
this.test = 'qwerty';
}
...
There was no error when I update an @Input
before input
signal.
Logically I would refactor this to:
@Component({ ... })
export class SomeComponent {
test = input(null);
ngOnInit() {
this.test.set('qwerty'); // <- set does not exist for input signal
}
...
So in the above code, input
signal does not have a set
or update
method, so my refactor is wrong, what is the logical way to solve this problem, the update must be done.
I am refactoring my angular code to work with signals. I have this below code, which needs to be refactored.
@Component({ ... })
export class SomeComponent {
@Input() test = null;
ngOnInit() {
this.test = 'qwerty';
}
...
There was no error when I update an @Input
before input
signal.
Logically I would refactor this to:
@Component({ ... })
export class SomeComponent {
test = input(null);
ngOnInit() {
this.test.set('qwerty'); // <- set does not exist for input signal
}
...
So in the above code, input
signal does not have a set
or update
method, so my refactor is wrong, what is the logical way to solve this problem, the update must be done.
2 Answers
Reset to default 0Signal inputs have two different types, one with input syntax and the other with model syntax. What you need is a model type. A model type input has the ability to be updated by both the parent component and the child component.
@Component({ ... })
export class SomeComponent {
test = model<string>();
ngOnInit() {
this.test.set('qwerty'); // now you can update.
}
...
form more : https://angular.dev/guide/components/inputs#model-inputs
Linked Signal:
We can solve this problem, by using a linkedSignal
which updates the local state when there are new updates from the input
signal, as well as having set
and update
methods to react to update the local state.
One more thing you should do is rename the signal input
to a different name, but use the alias
property to not change the HTML binding name (less refactoring in HTML side).
@Component({ ... })
export class SomeComponent {
// change the input signal name but use alias to keep the same binding name
readonly testInput = input(null, { alias: 'test' });
// linked signal takes the value of input signal, can be used for modify local state
// if new value comes from input signal, local state is overridden
readonly test = linkedSignal(() => this.testInput());
ngOnInit() {
this.test.set('qwerty'); // <- set does not exist for input signal
}
...
Without LinkedSignal:
If your angular does not have linkedSignal
(Before Angular 19), then you can use an effect
to achieve the same behavior:
@Component({ ... })
export class SomeComponent {
// change the input signal name but use alias to keep the same binding name
readonly testInput = input(null, { alias: 'test' });
readonly test = signal(undefined);
constructor() {
effect(() => {
this.test.set(this.testInput());
}, { allowSignalWrites: true });
}
ngOnInit() {
this.test.set('qwerty'); // <- set does not exist for input signal
}
...